jekyll-theme-conference 2.5.4 → 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +53 -41
  3. data/_includes/js/conference-live.js +199 -104
  4. data/_includes/js/conference-modal.js +32 -15
  5. data/_includes/js/conference-program.js +48 -0
  6. data/_includes/js/conference.js +11 -11
  7. data/_includes/js/jquery-3.5.1.min.js +2 -0
  8. data/_includes/partials/checks.html +66 -31
  9. data/_includes/partials/footer.html +4 -21
  10. data/_includes/partials/get_day_hash.html +20 -0
  11. data/_includes/partials/get_day_time.html +19 -0
  12. data/_includes/partials/get_link.html +56 -64
  13. data/_includes/partials/get_link_types.html +14 -14
  14. data/_includes/partials/get_live_timestamps.html +49 -0
  15. data/_includes/partials/get_main_category.html +9 -9
  16. data/_includes/partials/get_talk_time.html +7 -7
  17. data/_includes/partials/get_talk_timestamp.html +4 -0
  18. data/_includes/partials/get_time_pronoun.html +6 -0
  19. data/_includes/partials/header.html +15 -12
  20. data/_includes/partials/info_bar.html +22 -22
  21. data/_includes/partials/list_categories.html +2 -2
  22. data/_includes/partials/list_speakers.html +14 -18
  23. data/_includes/partials/list_sub_categories.html +7 -7
  24. data/_includes/partials/modal_link.html +21 -0
  25. data/_includes/partials/{live-modal.html → modal_live.html} +7 -10
  26. data/_includes/partials/navbar.html +32 -32
  27. data/_includes/partials/navbar_rooms.html +21 -20
  28. data/_includes/partials/{live_button.html → show_live_button.html} +6 -8
  29. data/_includes/partials/show_room.html +5 -5
  30. data/_includes/partials/show_talk.html +3 -3
  31. data/_includes/partials/show_talk_time.html +16 -2
  32. data/_layouts/data.html +91 -0
  33. data/_layouts/home.html +17 -18
  34. data/_layouts/program.html +179 -148
  35. data/_layouts/room.html +42 -38
  36. data/_layouts/speaker.html +40 -36
  37. data/_layouts/talk-overview.html +83 -53
  38. data/_layouts/talk.html +36 -34
  39. data/_sass/conference.scss +49 -17
  40. data/assets/icons/live.svg +33 -57
  41. data/assets/js/data.json +3 -0
  42. data/assets/js/main.js +0 -6
  43. metadata +15 -10
  44. data/_includes/js/conference-data.js +0 -87
  45. data/_includes/js/jquery-3.2.1.slim.min.js +0 -4
  46. data/_includes/partials/get_conf_time.html +0 -54
  47. data/_includes/partials/get_timestamp.html +0 -4
  48. 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: d6b3c4e4f2dd3a6f1d5964ff2dfccad58d737a96c58a4d34c7ee506d8ed50a07
4
+ data.tar.gz: a2f1f59ff4abbe070bc95702001270fc56e6abdb3e3e8fc274705d1bf9a4661c
5
5
  SHA512:
6
- metadata.gz: 54b43f0628ab99bf3c509bb75f7fab9d9bd390f41c1ac377f29e1f2f6a46f456b2281c74368fd6fad970e3d0f6a9043bb3831ffaeef4744177343006119427d5
7
- data.tar.gz: 8b109d80ee5ae3810cacb223840414953c757b91e50dac38b7c66d840277a937a263cfb4e2b72bb0dcd541223b24500418e461b859274849bb41af9025e22907
6
+ metadata.gz: b3424868268f6ff9003ae4a913f4d7985413db330bc2b8b4a4d94a15d39d496d5c21083e94e29d3242c56ae4f536d366b306cb7a2d80e5aedc3376c84b8332f6
7
+ data.tar.gz: 387fa9c0e9a183949314c800397a56c1e41f231301dfed0396751257f036ab4e2be319f98f67f06ea56897b0f72b54facb590664775822a6c280632008d48081
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
@@ -540,7 +552,7 @@ Links are used at different location throughout the theme: They can either be us
540
552
  Additionally, a navigation bar or main landing page link can also have the following properties:
541
553
 
542
554
  - `menu` containing another list of links. This creates a dropdown menu of multiple sublinks. The sublinks have the same properties as regular links, or
543
- - `live` making the link only visible during the conference and adds a live indication. The `name` property can be omitted. If streaming is enabled and any URL property is omitted, a click on the link will open the streaming modal (see section _Live Indications_ above).
555
+ - `live` making the link only visible during the conference and adds a live indication. The `name` property can be omitted. Using the optional `name_inactive` property shows a placeholder text while the conference is **not** live. If streaming is enabled and any URL property is omitted, a click on the link will open the streaming modal (see section _Live Indications_ above).
544
556
 
545
557
  Using the `file:` indicator, the relative address is automatically set as well as the icon. Using the `video:` indicator, the link is automatically configured to open in an iframe with a corresponding title and the icon is set.
546
558
 
@@ -1,14 +1,23 @@
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 data;
17
+
18
+ let confStart = {{ conf_start }};
19
+ let confEnd = {{ conf_end }};
20
+ let confDur = confEnd - confStart;
12
21
 
13
22
  let freezeTime = false;
14
23
  let timeFrozen = 0;
@@ -22,9 +31,19 @@
22
31
  let demoEnd = confEnd + confDur/durDemo*durPause;
23
32
 
24
33
  let liveTimer;
25
- let streamTimer;
34
+ let streamVideoTimer;
26
35
  let streamInfoTimer;
27
36
 
37
+ let loadData = function () {
38
+ $.getJSON('{{ site.baseurl }}/assets/js/data.json', function(json) {
39
+ data = json;
40
+ });
41
+ };
42
+
43
+ let getData = function () {
44
+ return data;
45
+ };
46
+
28
47
  let mod = function (n, m) {
29
48
  return ((n % m) + m) % m;
30
49
  };
@@ -80,10 +99,22 @@
80
99
  startUpdate();
81
100
  };
82
101
 
83
- let setTime = function (newTime) {
102
+ let setTime = function (newTime, newDay=1) {
84
103
  pauseTime();
85
104
 
86
- let d = new Date(confStart * 1000);
105
+ let dayIdx;
106
+ if (Number.isInteger(newDay)) {
107
+ dayIdx = newDay-1;
108
+ }
109
+ else if (/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(newDay)) {
110
+ dayIdx = data.days.find(o => o.name === newDay);
111
+ }
112
+ else {
113
+ dayIdx = data.days.find(o => o.name === newDay);
114
+ }
115
+ newDate = data.days[dayIdx].date;
116
+
117
+ let d = new Date(newDate);
87
118
  newTime = newTime.split(':');
88
119
  d.setHours(newTime[0], newTime[1]);
89
120
 
@@ -92,12 +123,13 @@
92
123
  update();
93
124
  };
94
125
 
95
- let getTime = function (tConvert = time()) {
126
+ let getTime = function (tConvert=time()) {
96
127
  let d = new Date(tConvert * 1000);
128
+ let dStr = d.toISOString().slice(0,10);
97
129
  let h = d.getHours();
98
130
  let m = d.getMinutes();
99
131
 
100
- return h + ":" + (m < 10 ? "0" : "") + m;
132
+ return dStr +" "+ h +":"+ (m < 10 ? "0" : "") + m;
101
133
  };
102
134
 
103
135
  let timeUnit = function () {
@@ -145,32 +177,38 @@
145
177
  let livePast = document.getElementsByClassName('live-past');
146
178
 
147
179
  for (let i = 0; i < liveShow.length; i++) {
148
- let tStart = liveShow[i].dataset.start;
149
- let tEnd = liveShow[i].dataset.end;
180
+ let tStarts = liveShow[i].dataset.start.split(',');
181
+ let tEnds = liveShow[i].dataset.end.split(',');
150
182
 
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');
183
+ for (let k = 0; k < tStarts.length; k++) {
184
+ if (tNow >= tStarts[k] && tNow < tEnds[k]) {
185
+ // Show when active
186
+ liveShow[i].classList.remove('d-none');
187
+ break;
188
+ }
189
+ else if (!liveShow[i].classList.contains('d-none')) {
190
+ // Hide otherwise
191
+ liveShow[i].classList.add('d-none');
192
+ }
158
193
  }
159
194
  }
160
195
 
161
196
  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');
197
+ let tStarts = liveHide[i].dataset.start.split(',');
198
+ let tEnds = liveHide[i].dataset.end.split(',');
199
+
200
+ for (let k = 0; k < tStarts.length; k++) {
201
+ if (tNow >= tStarts[k] && tNow < tEnds[k]) {
202
+ // Hide when active
203
+ if (!liveHide[i].classList.contains('d-none')) {
204
+ liveHide[i].classList.add('d-none');
205
+ break;
206
+ }
207
+ }
208
+ else {
209
+ // Show otherwise
210
+ liveHide[i].classList.remove('d-none');
169
211
  }
170
- }
171
- else {
172
- // Show otherwise
173
- liveHide[i].classList.remove('d-none');
174
212
  }
175
213
  }
176
214
 
@@ -281,101 +319,150 @@
281
319
  };
282
320
 
283
321
  {% if site.conference.live.streaming -%}
284
- {% include js/conference-data.js %}
322
+ let streamPause = {{ site.conference.live.streaming.time_pause | default: 60 }}; // in minutes
323
+ let streamPrepend = {{ site.conference.live.streaming.time_prepend | default: 5 }}; // in minutes
324
+ let streamExtend = {{ site.conference.live.streaming.time_extend | default: 5 }}; // in minutes
285
325
 
286
326
  let streamModal;
287
327
 
288
328
  let getRoom = function (roomName) {
289
- if (roomName in rooms) {
290
- return rooms[roomName];
329
+ if (roomName in data.rooms) {
330
+ return data.rooms[roomName];
291
331
  }
292
332
  else {
293
- return rooms[Object.keys(rooms)[0]];
333
+ return data.rooms[Object.keys(data.rooms)[0]];
294
334
  }
295
335
  };
296
336
 
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');
337
+ let getNextTalk = function (roomName) {
338
+ let timeNow = time();
339
+ let talksHere = data.talks[roomName];
304
340
 
305
- if (typeof streamTimer !== "undefined") {
306
- clearInterval(streamTimer);
341
+ if (typeof talksHere !== "undefined") {
342
+ if (timeNow < talksHere[talksHere.length-1].end) {
343
+ for (var i = 0; i < talksHere.length; i++) {
344
+ if (timeNow < talksHere[i].end) {
345
+ return talksHere[i];
346
+ }
347
+ }
348
+ }
307
349
  }
308
- if (!freezeTime) {
309
- streamTimer = setTimeout(activeStream, delayStart(room.start) * 1000, roomName);
350
+ return false;
351
+ };
352
+
353
+ let getNextPause = function (roomName) {
354
+ let timeNow = time();
355
+ let talksHere = data.talks[roomName];
356
+
357
+ if (typeof talksHere !== "undefined") {
358
+ if (timeNow < talksHere[talksHere.length-1].end) {
359
+ for (var i = 1; i < talksHere.length; i++) {
360
+ if (timeNow < talksHere[i].start && streamPause*60 <= talksHere[i].start - talksHere[i-1].end) {
361
+ return {
362
+ 'start': talksHere[i-1].end,
363
+ 'end': talksHere[i].start,
364
+ };
365
+ }
366
+ }
367
+ }
310
368
  }
369
+ return false;
311
370
  };
312
371
 
313
- let activeStream = function (roomName) {
314
- let room = getRoom(roomName);
372
+ let setStreamContent = function (content) {
373
+ streamModal.find('iframe').attr('src', '');
374
+ streamModal.find('iframe').addClass('d-none');
375
+ streamModal.find('#stream-placeholder > div').text(content);
376
+ streamModal.find('#stream-placeholder').addClass('d-flex');
377
+ };
315
378
 
316
- streamModal.find('iframe').attr('src', room.href);
379
+ let setStreamSrc = function (href) {
380
+ streamModal.find('iframe').attr('src', href);
317
381
  streamModal.find('#stream-placeholder').addClass('d-none').removeClass('d-flex');
318
382
  streamModal.find('iframe').removeClass('d-none');
383
+ };
319
384
 
320
- if (typeof streamTimer !== "undefined") {
321
- clearInterval(streamTimer);
322
- }
323
- if (!freezeTime) {
324
- streamTimer = setTimeout(postEndStream, delayStart(room.end) * 1000, roomName);
385
+ let setStreamVideo = function (roomName) {
386
+ let timeNow = time();
387
+
388
+ let talksHere = data.talks[roomName];
389
+ let roomStart = talksHere[0].start;
390
+ let roomEnd = talksHere[talksHere.length-1].end;
391
+
392
+ if (typeof streamVideoTimer !== "undefined") {
393
+ clearInterval(streamVideoTimer);
325
394
  }
326
- };
327
395
 
328
- let postEndStream = function (roomName) {
329
- let room = getRoom(roomName);
396
+ // Conference not yet started
397
+ if (timeNow < roomStart - streamPrepend*60) {
398
+ setStreamContent('{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}');
330
399
 
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');
400
+ if (!freezeTime) {
401
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomStart - streamPrepend*60) * 1000, roomName);
402
+ }
403
+ }
404
+
405
+ // Conference is over
406
+ else if (timeNow > roomEnd + streamExtend*60) {
407
+ setStreamContent('{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}');
335
408
 
336
- if (typeof streamTimer !== "undefined") {
337
- clearInterval(streamTimer);
409
+ if (!freezeTime && demo) {
410
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd - streamPrepend*60) * 1000, roomName);
411
+ }
338
412
  }
339
- if (!freezeTime && demo) {
340
- streamTimer = setTimeout(preStartStream, delayStart(demoStart) * 1000, roomName);
413
+
414
+ // Conference ongoing
415
+ else {
416
+ let pauseNext = getNextPause(roomName);
417
+
418
+ // Currently stream is paused
419
+ 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." }}');
421
+
422
+ if (!freezeTime) {
423
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.end - streamPrepend*60) * 1000, roomName);
424
+ }
425
+ }
426
+ // Currently a talk is active
427
+ else {
428
+ let room = getRoom(roomName);
429
+ setStreamSrc(room.href);
430
+
431
+ if (!freezeTime) {
432
+ if (pauseNext) {
433
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.start + streamExtend*60) * 1000, roomName);
434
+ }
435
+ else {
436
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd + streamExtend*60) * 1000, roomName);
437
+ }
438
+ }
439
+ }
341
440
  }
342
441
  };
343
442
 
344
443
  let setStreamInfo = function (roomName) {
345
444
  let timeNow = time();
346
- let talksHere = talks[roomName];
347
- let talkNow;
445
+ let talkNext = getNextTalk(roomName);
348
446
 
349
447
  if (typeof streamInfoTimer !== "undefined") {
350
448
  clearInterval(streamInfoTimer);
351
449
  }
352
450
 
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;
451
+ if (timeNow >= talkNext.start - streamPause*60) {
452
+ document.getElementById('stream-info').dataset.time = talkNext.start;
453
+ document.getElementById('stream-info-time').dataset.time = talkNext.start;
367
454
  updateLive();
368
455
 
369
456
  streamModal.find('#stream-info-color').removeClass(function (index, className) {
370
457
  return (className.match(/(^|\s)border-soft-\S+/g) || []).join(' ');
371
458
  });
372
- streamModal.find('#stream-info-color').addClass('border-soft-' + talkNow.color);
459
+ streamModal.find('#stream-info-color').addClass('border-soft-' + talkNext.color);
373
460
 
374
- streamModal.find('#stream-info-talk').text(talkNow.name).attr('href', talkNow.href);
461
+ streamModal.find('#stream-info-talk').text(talkNext.name).attr('href', talkNext.href);
375
462
 
376
463
  let speakerStr = '';
377
- for (var i = 0; i < talkNow.speakers.length; i++) {
378
- let speaker = speakers[talkNow.speakers[i]];
464
+ for (var i = 0; i < talkNext.speakers.length; i++) {
465
+ let speaker = data.speakers[talkNext.speakers[i]];
379
466
  if (speaker.href == '') {
380
467
  speakerStr += speaker.name +', '
381
468
  }
@@ -389,35 +476,37 @@
389
476
  streamModal.find('#stream-info').removeClass('d-none');
390
477
 
391
478
  if (!freezeTime) {
392
- streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNow.end) * 1000, roomName);
479
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.end) * 1000, roomName);
393
480
  }
394
481
  }
395
482
  else {
396
483
  streamModal.find('#stream-info').addClass('d-none');
484
+
485
+ if (!freezeTime) {
486
+ if (talkNext) {
487
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.start - streamPause*60) * 1000, roomName);
488
+ }
489
+ else if (demo) {
490
+ let talksHere = data.talks[roomName];
491
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talksHere[0].start - streamPrepend*60) * 1000, roomName);
492
+ }
493
+ }
397
494
  }
398
495
  };
399
496
 
400
497
  let setStream = function (roomName) {
401
498
  streamModal.find('.modal-footer .btn').removeClass('active');
402
- streamModal.find('#stream-select').selectedIndex = -1;
499
+ streamModal.find('#stream-select').val(0);
403
500
 
501
+ // Recover room name in case of empty default
404
502
  let room = getRoom(roomName);
405
503
  roomName = room.name;
406
- let tNow = time();
407
504
 
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
- }
505
+ setStreamVideo(roomName);
417
506
  setStreamInfo(roomName);
418
507
 
419
508
  streamModal.find('#stream-button' + room.id).addClass('active');
420
- streamModal.find('#stream-select').selectedIndex = room.id;
509
+ streamModal.find('#stream-select').val(room.id);
421
510
  };
422
511
 
423
512
  let updateStream = function () {
@@ -432,8 +521,8 @@
432
521
  };
433
522
 
434
523
  let stopUpdateStream = function () {
435
- if (typeof streamTimer !== "undefined") {
436
- clearInterval(streamTimer);
524
+ if (typeof streamVideoTimer !== "undefined") {
525
+ clearInterval(streamVideoTimer);
437
526
  }
438
527
  if (typeof streamInfoTimer !== "undefined") {
439
528
  clearInterval(streamInfoTimer);
@@ -449,6 +538,7 @@
449
538
  let setupStream = function () {
450
539
  streamModal = $('#stream-modal');
451
540
 
541
+ // configure modal opening buttons
452
542
  streamModal.on('show.bs.modal', function (event) {
453
543
  let button = $(event.relatedTarget);
454
544
  let roomName = button.data('room');
@@ -458,6 +548,7 @@
458
548
  hideModal(event);
459
549
  });
460
550
 
551
+ // configure room selection buttons in modal
461
552
  streamModal.find('.modal-footer .btn').on('click', function(event) {
462
553
  event.preventDefault();
463
554
 
@@ -465,6 +556,7 @@
465
556
  setStream(roomName);
466
557
  });
467
558
 
559
+ // configure room selection menu in modal
468
560
  streamModal.find('#stream-select').on('change', function(event) {
469
561
  event.preventDefault();
470
562
 
@@ -474,6 +566,7 @@
474
566
  };
475
567
 
476
568
  let setup = function () {
569
+ loadData();
477
570
  startUpdateLive();
478
571
  setupStream();
479
572
  };
@@ -496,6 +589,7 @@
496
589
  {%- else -%}
497
590
 
498
591
  let setup = function () {
592
+ loadData();
499
593
  startUpdateLive();
500
594
  };
501
595
 
@@ -515,6 +609,7 @@
515
609
 
516
610
  return {
517
611
  init: setup,
612
+ getData: getData,
518
613
 
519
614
  pauseTime: pauseTime,
520
615
  continueTime: continueTime,