jekyll-theme-conference 2.5.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +52 -40
  3. data/_includes/js/conference-live.js +188 -102
  4. data/_includes/js/conference-program.js +48 -0
  5. data/_includes/js/conference.js +11 -11
  6. data/_includes/js/jquery-3.5.1.min.js +2 -0
  7. data/_includes/partials/checks.html +66 -31
  8. data/_includes/partials/footer.html +3 -3
  9. data/_includes/partials/get_day_hash.html +20 -0
  10. data/_includes/partials/get_day_time.html +19 -0
  11. data/_includes/partials/get_link.html +41 -41
  12. data/_includes/partials/get_link_types.html +14 -14
  13. data/_includes/partials/get_live_timestamps.html +49 -0
  14. data/_includes/partials/get_main_category.html +9 -9
  15. data/_includes/partials/get_talk_time.html +7 -7
  16. data/_includes/partials/get_talk_timestamp.html +4 -0
  17. data/_includes/partials/get_time_pronoun.html +6 -0
  18. data/_includes/partials/header.html +15 -12
  19. data/_includes/partials/info_bar.html +22 -22
  20. data/_includes/partials/list_categories.html +2 -2
  21. data/_includes/partials/list_speakers.html +14 -18
  22. data/_includes/partials/list_sub_categories.html +7 -7
  23. data/_includes/partials/{live-modal.html → live_modal.html} +4 -7
  24. data/_includes/partials/navbar.html +25 -33
  25. data/_includes/partials/navbar_rooms.html +21 -20
  26. data/_includes/partials/{live_button.html → show_live_button.html} +6 -8
  27. data/_includes/partials/show_room.html +5 -5
  28. data/_includes/partials/show_talk.html +3 -3
  29. data/_includes/partials/show_talk_time.html +16 -2
  30. data/_layouts/data.html +91 -0
  31. data/_layouts/home.html +2 -10
  32. data/_layouts/program.html +179 -148
  33. data/_layouts/room.html +42 -38
  34. data/_layouts/speaker.html +40 -36
  35. data/_layouts/talk-overview.html +83 -53
  36. data/_layouts/talk.html +36 -34
  37. data/_sass/conference.scss +29 -7
  38. data/assets/icons/live.svg +33 -57
  39. data/assets/js/data.json +3 -0
  40. data/assets/js/main.js +0 -6
  41. metadata +13 -9
  42. data/_includes/js/conference-data.js +0 -87
  43. data/_includes/js/jquery-3.2.1.slim.min.js +0 -4
  44. data/_includes/partials/get_conf_time.html +0 -54
  45. data/_includes/partials/get_timestamp.html +0 -4
  46. data/_layouts/delete_hidden.html +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbbe3c769ff41772597a229dc226732d868691b98d006c4767a569a4ef0b4d14
4
- data.tar.gz: ffd668e698af13d076e91823355b69550a0e0486cee4b0be54c0db7f5c1a5916
3
+ metadata.gz: b4319ed637aa4734e12cd0d9eef3a807f314e8a9e4c0ff3a79b8781e8e00ebb9
4
+ data.tar.gz: d0c52c4aa84e87fb5c9892b6509db3de79a640e2e3ad005359febda835c412be
5
5
  SHA512:
6
- metadata.gz: 54b43f0628ab99bf3c509bb75f7fab9d9bd390f41c1ac377f29e1f2f6a46f456b2281c74368fd6fad970e3d0f6a9043bb3831ffaeef4744177343006119427d5
7
- data.tar.gz: 8b109d80ee5ae3810cacb223840414953c757b91e50dac38b7c66d840277a937a263cfb4e2b72bb0dcd541223b24500418e461b859274849bb41af9025e22907
6
+ metadata.gz: 849e5facbe864d96c63fcdcd218ee4a4a4d8e63a9787aca58c10b1fafdf20704ce3d529caa519940ae65bd3a561ffc6127f2da243a823e676604b538e2f24c35
7
+ data.tar.gz: 5bca6a3b8624e8e8f04797292cc969dd2f995fb74ffedd178dee2d59b0410cd93d1dd5479d8c64cdc99728ca7160e05c31e9537a93866093ed88bd65142e0a03
data/README.md CHANGED
@@ -2,17 +2,16 @@
2
2
 
3
3
  ![Screenshot](screenshot.png)
4
4
 
5
- This is a [Jekyll](http://jekyllrb.com) theme based on [Bootstrap 4](http://getbootstrap.com) which can be used to make a simple, responsive website for a one-day conference or workshop with parallel tracks containing:
5
+ This is a responsive [Jekyll](http://jekyllrb.com) theme based on [Bootstrap 4](http://getbootstrap.com) for conferences. It contains
6
6
 
7
- - program / schedule,
8
- - talk and speaker descriptions with
9
- + links to slides, and
10
- + embedded recordings,
7
+ - multiday program / schedule,
8
+ - talk and speaker descriptions,
11
9
  - map for directions,
12
- - live indication and embedded video streaming.
10
+ - realtime live indications during the conference, and
11
+ - supports embedded video streaming or recordings.
13
12
 
14
- All components such as talks, speakers or rooms are represented as collection of files. The schedule is given is defined via a simple structure stored in a [YAML](https://en.wikipedia.org/wiki/YAML) file. There is no need for databases and once generated the website consists only of static files. A script and workflows are available for easy import, e.g. [frab](https://github.com/frab/frab/wiki/Manual#introduction) compatible schedules.
15
- The design is easily modifiable and is adapted for mobile uses and printing.
13
+ All components such as talks, speakers or rooms are represented as collection of files. The schedule is given is defined via a simple structure stored in a [YAML](https://en.wikipedia.org/wiki/YAML) file. There is no need for databases and once generated the website consists only of static files. A script and workflows are available for easy import, e.g. of [frab](https://github.com/frab/frab/wiki/Manual#introduction) compatible schedules.
14
+ The design is easily customizable and is adapted for mobile uses and printing.
16
15
 
17
16
  The theme was originally created for the yearly Winterkongress conference of the [Digital Society Switzerland](https://digitale-gesellschaft.ch/). You can see this theme in action here:
18
17
 
@@ -139,14 +138,6 @@ To get started, simply copy the desired workflow file to your repository and ada
139
138
 
140
139
  - `_tools/build.yml` -> `.github/workflows/build.yml`
141
140
 
142
- Hidden rooms, speakers, or talks are automatically generated in way containing no content. In order to remove these empty files simply add a file called `delete_hidden.sh` to the root with the following content. It will automatically called by the `build` workflow (if available) to delete the files.
143
-
144
- ```markdown
145
- ---
146
- layout: delete_hidden
147
- ---
148
- ```
149
-
150
141
 
151
142
  ## Configuration
152
143
 
@@ -330,21 +321,23 @@ In order to help users navigating the program during the congress, a _Live_ indi
330
321
 
331
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).
332
323
 
333
- In order to activate the functionality the `live` property has to be set containing
324
+ 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
334
325
 
335
- - the date of the day at which the conference takes place (`date`),
336
- - the timezone in which the conference takes place (`timezone`),
337
- - optionally if streaming is enabled (`streaming`) with indications how many minutes early the stream will begin and end, and
326
+ - how long a pause between two consecutive talks has to be for the live indication to pause (`time_stop`),
327
+ - optionally if streaming is enabled (`streaming`) with indications
328
+ + 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`),
338
331
  - optionally a demo mode setting, whereby the JavaScript function cycles through the entire program in five minutes for demonstration purposes (`demo: true`, default: `false`).
339
332
 
340
333
  ```yaml
341
334
  conference:
342
335
  live:
343
- date: 01.01.2020
344
- timezone: GMT+1
336
+ time_stop: 240 # in minutes
345
337
  streaming:
346
- start_early: 15 # in minutes
347
- end_late: 0 # in minutes
338
+ time_pause: 60 # in minutes
339
+ time_prepend: 5 # in minutes
340
+ time_extend: 5 # in minutes
348
341
  demo: false
349
342
  ```
350
343
 
@@ -466,33 +459,52 @@ The actual schedule defining when and in which room a talk takes place is stored
466
459
 
467
460
  ### Schedule / Program
468
461
 
469
- The schedule of the conference linking the talks with the rooms and indicating when each talk talks place and how long it goes is set in the `_data/program.yml` file. It consists of an array of rooms each consisting of a
462
+ The schedule of the conference linking the talks with the rooms and indicating when each talk talks place and how long it goes is set in the `_data/program.yml` file. It contains a list of days, whereby each day contains a list of rooms, whereby each room contains a list of talks.
463
+
464
+ Each day consists of
465
+
466
+ - a list of rooms (`rooms`) in which talks are taking place on that day
467
+ - optionally, the day's `name`, e.g. the weekday
468
+ - optionally, the short form of the day's name (`abbr`), and
469
+ - optionally only if no live indications are active, a `date` in the format `YYYY-MM-DD`.
470
470
 
471
- - `room` name (must correspond to one of the room identifier), and
472
- - an array of `talks` which also can be empty `[]`.
471
+ Each room consists of
473
472
 
474
- The order of the room in the file defines the order of the rooms on the website (program and room listings). Each talk in the array consists of
473
+ - the room's `name` (must correspond to one of the room identifier), and
474
+ - a list of talks (`talks`) which also can be empty `[]`.
475
+
476
+ The order of the rooms in the list defines the order of the rooms as shown in the schedule on the program page. For the live streaming or the room overview the order of the rooms is alphabetical but can be adapted via the [main configuration file](https://jekyllrb.com/docs/collections/#sort-by-front-matter-key).
477
+
478
+ Each talk consists of
475
479
 
476
480
  - a `name` (must correspond to one of the talk identifier),
477
481
  - a starting time `time_start` given as `H:M` ([`strftime`](http://www.strfti.me) formated), and
478
482
  - an end time `time_end`.
479
483
 
480
- The array should (manually) be ordered by time. Currently talks can only take place on the same day and multi-day conferences are not supported.
484
+ The list of talks should (manually) be ordered by time, i.e. the first occurring talk should be listed first.
481
485
 
482
486
  Example:
483
487
 
484
488
  ```yaml
485
- - room: Room A
486
- talks:
487
- - name: Vim Impetus Placerat Cotidieque Ad
488
- time_start: '12:00'
489
- time_end: '12:45'
490
- - name: Condimentum Vitae Sapien Pellentesque
491
- time_start: '12:45'
492
- time_end: '13:30'
493
- - room: Room B
494
- talks:
495
- ...
489
+ days:
490
+ - name: Monday
491
+ abbr: Mo
492
+ date: 2020-01-31
493
+ rooms:
494
+ - name: Room A
495
+ talks:
496
+ - name: Vim Impetus Placerat Cotidieque Ad
497
+ time_start: '12:00'
498
+ time_end: '12:45'
499
+ - name: Condimentum Vitae Sapien Pellentesque
500
+ time_start: '12:45'
501
+ time_end: '13:30'
502
+
503
+ - name: Room B
504
+ talks:
505
+ - name: Arcu Non Odio
506
+ time_start: '12:00'
507
+ time_end: '13:00'
496
508
  ```
497
509
 
498
510
  ### Talks
@@ -1,14 +1,21 @@
1
- window.conference.live = (function() {
2
- {%- include partials/get_conf_time.html -%}
3
- {%- assign time_start = conf_start -%}
4
- {%- assign time_end = conf_end -%}
5
- {%- include partials/get_timestamp.html -%}
6
-
7
- let confStart = {{ timestamp_start }};
8
- let confEnd = {{ timestamp_end }};
9
- let confDur = confEnd - confStart;
1
+ window.conference.live = (function() {
2
+ {% assign d = site.data.program.days | first -%}
3
+ {%- include partials/get_day_time.html -%}
4
+ {%- assign t = day_start_talk -%}
5
+
6
+ {%- include partials/get_talk_timestamp.html -%}
7
+ {%- assign conf_start = timestamp_start -%}
8
+
9
+ {%- assign d = site.data.program.days | last -%}
10
+ {%- include partials/get_day_time.html -%}
11
+ {%- assign t = day_end_talk -%}
10
12
 
11
- let talkAnnounce = 120; // in minutes
13
+ {%- include partials/get_talk_timestamp.html -%}
14
+ {%- assign conf_end = timestamp_end -%}
15
+
16
+ let confStart = {{ conf_start }};
17
+ let confEnd = {{ conf_end }};
18
+ let confDur = confEnd - confStart;
12
19
 
13
20
  let freezeTime = false;
14
21
  let timeFrozen = 0;
@@ -22,7 +29,7 @@
22
29
  let demoEnd = confEnd + confDur/durDemo*durPause;
23
30
 
24
31
  let liveTimer;
25
- let streamTimer;
32
+ let streamVideoTimer;
26
33
  let streamInfoTimer;
27
34
 
28
35
  let mod = function (n, m) {
@@ -80,10 +87,22 @@
80
87
  startUpdate();
81
88
  };
82
89
 
83
- let setTime = function (newTime) {
90
+ let setTime = function (newTime, newDay=1) {
84
91
  pauseTime();
85
92
 
86
- let d = new Date(confStart * 1000);
93
+ let dayIdx;
94
+ if (Number.isInteger(newDay)) {
95
+ dayIdx = newDay-1;
96
+ }
97
+ else if (/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(newDay)) {
98
+ dayIdx = data.days.find(o => o.name === newDay);
99
+ }
100
+ else {
101
+ dayIdx = data.days.find(o => o.name === newDay);
102
+ }
103
+ newDate = data.days[dayIdx].date;
104
+
105
+ let d = new Date(newDate);
87
106
  newTime = newTime.split(':');
88
107
  d.setHours(newTime[0], newTime[1]);
89
108
 
@@ -92,12 +111,13 @@
92
111
  update();
93
112
  };
94
113
 
95
- let getTime = function (tConvert = time()) {
114
+ let getTime = function (tConvert=time()) {
96
115
  let d = new Date(tConvert * 1000);
116
+ let dStr = d.toISOString().slice(0,10);
97
117
  let h = d.getHours();
98
118
  let m = d.getMinutes();
99
119
 
100
- return h + ":" + (m < 10 ? "0" : "") + m;
120
+ return dStr +" "+ h +":"+ (m < 10 ? "0" : "") + m;
101
121
  };
102
122
 
103
123
  let timeUnit = function () {
@@ -145,32 +165,38 @@
145
165
  let livePast = document.getElementsByClassName('live-past');
146
166
 
147
167
  for (let i = 0; i < liveShow.length; i++) {
148
- let tStart = liveShow[i].dataset.start;
149
- let tEnd = liveShow[i].dataset.end;
168
+ let tStarts = liveShow[i].dataset.start.split(',');
169
+ let tEnds = liveShow[i].dataset.end.split(',');
150
170
 
151
- if (tNow >= tStart && tNow < tEnd) {
152
- // Show when active
153
- liveShow[i].classList.remove('d-none');
154
- }
155
- else if (!liveShow[i].classList.contains('d-none')) {
156
- // Hide otherwise
157
- liveShow[i].classList.add('d-none');
171
+ for (let k = 0; k < tStarts.length; k++) {
172
+ if (tNow >= tStarts[k] && tNow < tEnds[k]) {
173
+ // Show when active
174
+ liveShow[i].classList.remove('d-none');
175
+ break;
176
+ }
177
+ else if (!liveShow[i].classList.contains('d-none')) {
178
+ // Hide otherwise
179
+ liveShow[i].classList.add('d-none');
180
+ }
158
181
  }
159
182
  }
160
183
 
161
184
  for (let i = 0; i < liveHide.length; i++) {
162
- let tStart = liveHide[i].dataset.start;
163
- let tEnd = liveHide[i].dataset.end;
164
-
165
- if (tNow >= tStart && tNow < tEnd) {
166
- // Hide when active
167
- if (!liveHide[i].classList.contains('d-none')) {
168
- liveHide[i].classList.add('d-none');
185
+ let tStarts = liveHide[i].dataset.start.split(',');
186
+ let tEnds = liveHide[i].dataset.end.split(',');
187
+
188
+ for (let k = 0; k < tStarts.length; k++) {
189
+ if (tNow >= tStarts[k] && tNow < tEnds[k]) {
190
+ // Hide when active
191
+ if (!liveHide[i].classList.contains('d-none')) {
192
+ liveHide[i].classList.add('d-none');
193
+ break;
194
+ }
195
+ }
196
+ else {
197
+ // Show otherwise
198
+ liveHide[i].classList.remove('d-none');
169
199
  }
170
- }
171
- else {
172
- // Show otherwise
173
- liveHide[i].classList.remove('d-none');
174
200
  }
175
201
  }
176
202
 
@@ -281,101 +307,151 @@
281
307
  };
282
308
 
283
309
  {% if site.conference.live.streaming -%}
284
- {% include js/conference-data.js %}
310
+ let streamPause = {{ site.conference.live.streaming.time_pause | default: 60 }}; // in minutes
311
+ let streamPrepend = {{ site.conference.live.streaming.time_prepend | default: 5 }}; // in minutes
312
+ let streamExtend = {{ site.conference.live.streaming.time_extend | default: 5 }}; // in minutes
285
313
 
286
314
  let streamModal;
315
+ let data;
287
316
 
288
317
  let getRoom = function (roomName) {
289
- if (roomName in rooms) {
290
- return rooms[roomName];
318
+ if (roomName in data.rooms) {
319
+ return data.rooms[roomName];
291
320
  }
292
321
  else {
293
- return rooms[Object.keys(rooms)[0]];
322
+ return data.rooms[Object.keys(data.rooms)[0]];
294
323
  }
295
324
  };
296
325
 
297
- let preStartStream = function (roomName) {
298
- let room = getRoom(roomName);
299
-
300
- streamModal.find('iframe').attr('src', '');
301
- streamModal.find('iframe').addClass('d-none');
302
- streamModal.find('#stream-placeholder > div').text('{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}');
303
- streamModal.find('#stream-placeholder').addClass('d-flex');
326
+ let getNextTalk = function (roomName) {
327
+ let timeNow = time();
328
+ let talksHere = data.talks[roomName];
304
329
 
305
- if (typeof streamTimer !== "undefined") {
306
- clearInterval(streamTimer);
330
+ if (typeof talksHere !== "undefined") {
331
+ if (timeNow < talksHere[talksHere.length-1].end) {
332
+ for (var i = 0; i < talksHere.length; i++) {
333
+ if (timeNow < talksHere[i].end) {
334
+ return talksHere[i];
335
+ }
336
+ }
337
+ }
307
338
  }
308
- if (!freezeTime) {
309
- streamTimer = setTimeout(activeStream, delayStart(room.start) * 1000, roomName);
339
+ return false;
340
+ };
341
+
342
+ let getNextPause = function (roomName) {
343
+ let timeNow = time();
344
+ let talksHere = data.talks[roomName];
345
+
346
+ if (typeof talksHere !== "undefined") {
347
+ if (timeNow < talksHere[talksHere.length-1].end) {
348
+ for (var i = 1; i < talksHere.length; i++) {
349
+ if (timeNow < talksHere[i].start && streamPause*60 <= talksHere[i].start - talksHere[i-1].end) {
350
+ return {
351
+ 'start': talksHere[i-1].end,
352
+ 'end': talksHere[i].start,
353
+ };
354
+ }
355
+ }
356
+ }
310
357
  }
358
+ return false;
311
359
  };
312
360
 
313
- let activeStream = function (roomName) {
314
- let room = getRoom(roomName);
361
+ let setStreamContent = function (content) {
362
+ streamModal.find('iframe').attr('src', '');
363
+ streamModal.find('iframe').addClass('d-none');
364
+ streamModal.find('#stream-placeholder > div').text(content);
365
+ streamModal.find('#stream-placeholder').addClass('d-flex');
366
+ };
315
367
 
316
- streamModal.find('iframe').attr('src', room.href);
368
+ let setStreamSrc = function (href) {
369
+ streamModal.find('iframe').attr('src', href);
317
370
  streamModal.find('#stream-placeholder').addClass('d-none').removeClass('d-flex');
318
371
  streamModal.find('iframe').removeClass('d-none');
372
+ };
319
373
 
320
- if (typeof streamTimer !== "undefined") {
321
- clearInterval(streamTimer);
322
- }
323
- if (!freezeTime) {
324
- streamTimer = setTimeout(postEndStream, delayStart(room.end) * 1000, roomName);
374
+ let setStreamVideo = function (roomName) {
375
+ let timeNow = time();
376
+
377
+ let talksHere = data.talks[roomName];
378
+ let roomStart = talksHere[0].start;
379
+ let roomEnd = talksHere[talksHere.length-1].end;
380
+
381
+ if (typeof streamVideoTimer !== "undefined") {
382
+ clearInterval(streamVideoTimer);
325
383
  }
326
- };
327
384
 
328
- let postEndStream = function (roomName) {
329
- let room = getRoom(roomName);
385
+ // Conference not yet started
386
+ if (timeNow < roomStart - streamPrepend*60) {
387
+ setStreamContent('{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}');
330
388
 
331
- streamModal.find('iframe').attr('src', '');
332
- streamModal.find('iframe').addClass('d-none');
333
- streamModal.find('#stream-placeholder > div').text('{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}');
334
- streamModal.find('#stream-placeholder').addClass('d-flex');
389
+ if (!freezeTime) {
390
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomStart - streamPrepend*60) * 1000, roomName);
391
+ }
392
+ }
393
+
394
+ // Conference is over
395
+ else if (timeNow > roomEnd + streamExtend*60) {
396
+ setStreamContent('{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}');
335
397
 
336
- if (typeof streamTimer !== "undefined") {
337
- clearInterval(streamTimer);
398
+ if (!freezeTime && demo) {
399
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd - streamPrepend*60) * 1000, roomName);
400
+ }
338
401
  }
339
- if (!freezeTime && demo) {
340
- streamTimer = setTimeout(preStartStream, delayStart(demoStart) * 1000, roomName);
402
+
403
+ // Conference ongoing
404
+ else {
405
+ let pauseNext = getNextPause(roomName);
406
+
407
+ // Currently stream is paused
408
+ 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." }}');
410
+
411
+ if (!freezeTime) {
412
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.end - streamPrepend*60) * 1000, roomName);
413
+ }
414
+ }
415
+ // Currently a talk is active
416
+ else {
417
+ let room = getRoom(roomName);
418
+ setStreamSrc(room.href);
419
+
420
+ if (!freezeTime) {
421
+ if (pauseNext) {
422
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.start + streamExtend*60) * 1000, roomName);
423
+ }
424
+ else {
425
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd + streamExtend*60) * 1000, roomName);
426
+ }
427
+ }
428
+ }
341
429
  }
342
430
  };
343
431
 
344
432
  let setStreamInfo = function (roomName) {
345
433
  let timeNow = time();
346
- let talksHere = talks[roomName];
347
- let talkNow;
434
+ let talkNext = getNextTalk(roomName);
348
435
 
349
436
  if (typeof streamInfoTimer !== "undefined") {
350
437
  clearInterval(streamInfoTimer);
351
438
  }
352
439
 
353
- if (typeof talksHere !== "undefined") {
354
- if (timeNow < talksHere[talksHere.length-1].end) {
355
- for (var i = 0; i < talksHere.length; i++) {
356
- if (timeNow < talksHere[i].end && timeNow >= talksHere[i].start - talkAnnounce*60) {
357
- talkNow = talksHere[i];
358
- break;
359
- }
360
- }
361
- }
362
- }
363
-
364
- if (typeof talkNow !== "undefined") {
365
- document.getElementById('stream-info').dataset.time = talkNow.start;
366
- document.getElementById('stream-info-time').dataset.time = talkNow.start;
440
+ if (timeNow >= talkNext.start - streamPause*60) {
441
+ document.getElementById('stream-info').dataset.time = talkNext.start;
442
+ document.getElementById('stream-info-time').dataset.time = talkNext.start;
367
443
  updateLive();
368
444
 
369
445
  streamModal.find('#stream-info-color').removeClass(function (index, className) {
370
446
  return (className.match(/(^|\s)border-soft-\S+/g) || []).join(' ');
371
447
  });
372
- streamModal.find('#stream-info-color').addClass('border-soft-' + talkNow.color);
448
+ streamModal.find('#stream-info-color').addClass('border-soft-' + talkNext.color);
373
449
 
374
- streamModal.find('#stream-info-talk').text(talkNow.name).attr('href', talkNow.href);
450
+ streamModal.find('#stream-info-talk').text(talkNext.name).attr('href', talkNext.href);
375
451
 
376
452
  let speakerStr = '';
377
- for (var i = 0; i < talkNow.speakers.length; i++) {
378
- let speaker = speakers[talkNow.speakers[i]];
453
+ for (var i = 0; i < talkNext.speakers.length; i++) {
454
+ let speaker = data.speakers[talkNext.speakers[i]];
379
455
  if (speaker.href == '') {
380
456
  speakerStr += speaker.name +', '
381
457
  }
@@ -389,11 +465,21 @@
389
465
  streamModal.find('#stream-info').removeClass('d-none');
390
466
 
391
467
  if (!freezeTime) {
392
- streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNow.end) * 1000, roomName);
468
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.end) * 1000, roomName);
393
469
  }
394
470
  }
395
471
  else {
396
472
  streamModal.find('#stream-info').addClass('d-none');
473
+
474
+ if (!freezeTime) {
475
+ if (talkNext) {
476
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.start - streamPause*60) * 1000, roomName);
477
+ }
478
+ else if (demo) {
479
+ let talksHere = data.talks[roomName];
480
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talksHere[0].start - streamPrepend*60) * 1000, roomName);
481
+ }
482
+ }
397
483
  }
398
484
  };
399
485
 
@@ -401,19 +487,11 @@
401
487
  streamModal.find('.modal-footer .btn').removeClass('active');
402
488
  streamModal.find('#stream-select').selectedIndex = -1;
403
489
 
490
+ // Recover room name in case of empty default
404
491
  let room = getRoom(roomName);
405
492
  roomName = room.name;
406
- let tNow = time();
407
493
 
408
- if (tNow < room.start) {
409
- preStartStream(roomName);
410
- }
411
- else if (tNow > room.end) {
412
- postEndStream(roomName);
413
- }
414
- else {
415
- activeStream(roomName);
416
- }
494
+ setStreamVideo(roomName);
417
495
  setStreamInfo(roomName);
418
496
 
419
497
  streamModal.find('#stream-button' + room.id).addClass('active');
@@ -432,8 +510,8 @@
432
510
  };
433
511
 
434
512
  let stopUpdateStream = function () {
435
- if (typeof streamTimer !== "undefined") {
436
- clearInterval(streamTimer);
513
+ if (typeof streamVideoTimer !== "undefined") {
514
+ clearInterval(streamVideoTimer);
437
515
  }
438
516
  if (typeof streamInfoTimer !== "undefined") {
439
517
  clearInterval(streamInfoTimer);
@@ -449,6 +527,7 @@
449
527
  let setupStream = function () {
450
528
  streamModal = $('#stream-modal');
451
529
 
530
+ // configure modal opening buttons
452
531
  streamModal.on('show.bs.modal', function (event) {
453
532
  let button = $(event.relatedTarget);
454
533
  let roomName = button.data('room');
@@ -458,6 +537,7 @@
458
537
  hideModal(event);
459
538
  });
460
539
 
540
+ // configure room selection buttons in modal
461
541
  streamModal.find('.modal-footer .btn').on('click', function(event) {
462
542
  event.preventDefault();
463
543
 
@@ -465,12 +545,18 @@
465
545
  setStream(roomName);
466
546
  });
467
547
 
548
+ // configure room selection menu in modal
468
549
  streamModal.find('#stream-select').on('change', function(event) {
469
550
  event.preventDefault();
470
551
 
471
552
  let roomName = $(this).children('option:selected').text();
472
553
  setStream(roomName);
473
554
  });
555
+
556
+ // load data
557
+ $.getJSON('{{ site.baseurl }}/assets/js/data.json', function(json) {
558
+ data = json;
559
+ });
474
560
  };
475
561
 
476
562
  let setup = function () {