jekyll-theme-conference 2.5.3 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +85 -50
- data/_includes/js/conference-live.js +193 -104
- data/_includes/js/conference-modal.js +32 -15
- data/_includes/js/conference-program.js +48 -0
- data/_includes/js/conference.js +11 -11
- data/_includes/js/jquery-3.5.1.min.js +2 -0
- data/_includes/partials/checks.html +66 -31
- data/_includes/partials/footer.html +4 -21
- data/_includes/partials/get_day_hash.html +20 -0
- data/_includes/partials/get_day_time.html +19 -0
- data/_includes/partials/get_link.html +56 -64
- data/_includes/partials/get_link_types.html +14 -14
- data/_includes/partials/get_live_timestamps.html +49 -0
- data/_includes/partials/get_main_category.html +9 -9
- data/_includes/partials/get_talk_time.html +7 -7
- data/_includes/partials/get_talk_timestamp.html +4 -0
- data/_includes/partials/get_time_pronoun.html +6 -0
- data/_includes/partials/header.html +15 -12
- data/_includes/partials/info_bar.html +22 -22
- data/_includes/partials/list_categories.html +2 -2
- data/_includes/partials/list_speakers.html +14 -18
- data/_includes/partials/list_sub_categories.html +7 -7
- data/_includes/partials/modal_link.html +21 -0
- data/_includes/partials/{live-modal.html → modal_live.html} +7 -10
- data/_includes/partials/navbar.html +32 -32
- data/_includes/partials/navbar_rooms.html +21 -20
- data/_includes/partials/{live_button.html → show_live_button.html} +6 -8
- data/_includes/partials/show_room.html +5 -5
- data/_includes/partials/show_talk.html +3 -3
- data/_includes/partials/show_talk_duration.html +1 -1
- data/_includes/partials/show_talk_time.html +16 -2
- data/_layouts/data.html +91 -0
- data/_layouts/home.html +17 -18
- data/_layouts/program.html +179 -148
- data/_layouts/room.html +42 -38
- data/_layouts/speaker.html +41 -39
- data/_layouts/talk-overview.html +83 -53
- data/_layouts/talk.html +38 -39
- data/_sass/conference.scss +43 -17
- data/assets/icons/live.svg +33 -57
- data/assets/js/data.json +3 -0
- data/assets/js/main.js +0 -6
- metadata +14 -9
- data/_includes/js/conference-data.js +0 -87
- data/_includes/js/jquery-3.2.1.slim.min.js +0 -4
- data/_includes/partials/get_conf_time.html +0 -54
- data/_includes/partials/get_timestamp.html +0 -4
- data/_layouts/delete_hidden.html +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59b89379465383973e17366c49208b0ef62eec5831c4839ceaf6fbea786b202b
|
4
|
+
data.tar.gz: a76584224d9800eaa13164bc3c4a53899e112e997b19d5a4dd552d31ebf3d14e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbb655bb816b95df9b9cfb7f2718dfaf266039b2e3e478772c3bab2c84669b00af7d967186a1c210eca8b26dccb4aae2b7b6988ca4ddb2894c9fb35717f25846
|
7
|
+
data.tar.gz: a0539aeddd100251a5fe1c74127df3e3fcd27ece5aa9b93d6a5847b12878eff277b0cbba2692846050e5101a29f12875d47a1cfa1db863481609a4c0f0e6a785
|
data/README.md
CHANGED
@@ -2,14 +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)
|
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
|
9
|
-
- map for directions
|
7
|
+
- multiday program / schedule,
|
8
|
+
- talk and speaker descriptions,
|
9
|
+
- map for directions,
|
10
|
+
- realtime live indications during the conference, and
|
11
|
+
- supports embedded video streaming or recordings.
|
10
12
|
|
11
|
-
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.
|
12
|
-
The design is easily
|
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.
|
13
15
|
|
14
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:
|
15
17
|
|
@@ -44,11 +46,7 @@ This allows for easier installation and updating as you don't have to manage any
|
|
44
46
|
theme: jekyll-theme-conference
|
45
47
|
```
|
46
48
|
|
47
|
-
4.
|
48
|
-
|
49
|
-
- `_data/lang.yml`
|
50
|
-
|
51
|
-
5. Continue with the _Setup_ section further below to customize the theme and add some content for your conference
|
49
|
+
4. Continue with the _Setup_ section further below to customize the theme and add some content for your conference
|
52
50
|
|
53
51
|
To update the theme run `bundle update`.
|
54
52
|
|
@@ -76,11 +74,7 @@ To install:
|
|
76
74
|
|
77
75
|
4. Add `remote_theme: "DigitaleGesellschaft/jekyll-theme-conference@2.0.0"` to your `_config.yml` file. Remove any other `theme:` or `remote_theme:` entry.
|
78
76
|
|
79
|
-
5.
|
80
|
-
|
81
|
-
- `_data/lang.yml`
|
82
|
-
|
83
|
-
6. Continue with the _Setup_ section further below to customize the theme and add some content for your conference
|
77
|
+
5. Continue with the _Setup_ section further below to customize the theme and add some content for your conference
|
84
78
|
|
85
79
|
|
86
80
|
## Setup
|
@@ -108,21 +102,41 @@ In order to be up and running simply use the default content of this repository
|
|
108
102
|
|
109
103
|
### Automatic Import
|
110
104
|
|
111
|
-
There exists a Python file in this repository, `create_entries.py`, which can be used to import content from a [frab](https://github.com/frab/frab/wiki/Manual#introduction) compatible JSON file or a CSV table and generate the different talk, speakers and room files automatically
|
105
|
+
There exists a Python file in this repository, `_tools/create_entries.py`, which can be used to import content from a [frab](https://github.com/frab/frab/wiki/Manual#introduction) compatible JSON file (e.g. from [pretalx.com](https://pretalx.com/p/about/)) or a CSV table and generate the different talk, speakers and room files automatically. It has as only dependency [PyYAML](https://pypi.org/project/PyYAML/):
|
106
|
+
|
107
|
+
1. Copy the file `_tools/create_entries.py` from this repository
|
108
|
+
|
109
|
+
2. Create a virtual environment and activate it
|
110
|
+
|
111
|
+
```bash
|
112
|
+
python -m venv venv
|
113
|
+
source venv/bin/activate
|
114
|
+
```
|
115
|
+
|
116
|
+
3. Install PyYAML
|
117
|
+
|
118
|
+
```bash
|
119
|
+
pip install pyyaml
|
120
|
+
```
|
121
|
+
|
122
|
+
4. Execute the script, e.g. to show the help type
|
123
|
+
|
124
|
+
```bash
|
125
|
+
python _tools/create_entries.py --help
|
126
|
+
```
|
127
|
+
|
112
128
|
|
113
129
|
### Automatic Build
|
114
130
|
|
115
|
-
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
|
131
|
+
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:
|
116
132
|
|
117
|
-
- `
|
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.
|
134
|
+
- `test.yml`: automatically tries to build the website upon a new pull request. It can thus be used as status check before merging.
|
135
|
+
- `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.
|
118
136
|
|
119
|
-
|
137
|
+
To get started, simply copy the desired workflow file to your repository and adapt it to your needs:
|
120
138
|
|
121
|
-
|
122
|
-
---
|
123
|
-
layout: delete_hidden
|
124
|
-
---
|
125
|
-
```
|
139
|
+
- `_tools/build.yml` -> `.github/workflows/build.yml`
|
126
140
|
|
127
141
|
|
128
142
|
## Configuration
|
@@ -307,21 +321,23 @@ In order to help users navigating the program during the congress, a _Live_ indi
|
|
307
321
|
|
308
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).
|
309
323
|
|
310
|
-
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
|
311
325
|
|
312
|
-
-
|
313
|
-
-
|
314
|
-
|
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`),
|
315
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`).
|
316
332
|
|
317
333
|
```yaml
|
318
334
|
conference:
|
319
335
|
live:
|
320
|
-
|
321
|
-
timezone: GMT+1
|
336
|
+
time_stop: 240 # in minutes
|
322
337
|
streaming:
|
323
|
-
|
324
|
-
|
338
|
+
time_pause: 60 # in minutes
|
339
|
+
time_prepend: 5 # in minutes
|
340
|
+
time_extend: 5 # in minutes
|
325
341
|
demo: false
|
326
342
|
```
|
327
343
|
|
@@ -443,33 +459,52 @@ The actual schedule defining when and in which room a talk takes place is stored
|
|
443
459
|
|
444
460
|
### Schedule / Program
|
445
461
|
|
446
|
-
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
|
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
|
447
465
|
|
448
|
-
- `
|
449
|
-
-
|
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`.
|
450
470
|
|
451
|
-
|
471
|
+
Each room consists of
|
472
|
+
|
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
|
452
479
|
|
453
480
|
- a `name` (must correspond to one of the talk identifier),
|
454
481
|
- a starting time `time_start` given as `H:M` ([`strftime`](http://www.strfti.me) formated), and
|
455
482
|
- an end time `time_end`.
|
456
483
|
|
457
|
-
The
|
484
|
+
The list of talks should (manually) be ordered by time, i.e. the first occurring talk should be listed first.
|
458
485
|
|
459
486
|
Example:
|
460
487
|
|
461
488
|
```yaml
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
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'
|
473
508
|
```
|
474
509
|
|
475
510
|
### Talks
|
@@ -517,7 +552,7 @@ Links are used at different location throughout the theme: They can either be us
|
|
517
552
|
Additionally, a navigation bar or main landing page link can also have the following properties:
|
518
553
|
|
519
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
|
520
|
-
- `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).
|
521
556
|
|
522
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.
|
523
558
|
|
@@ -1,14 +1,21 @@
|
|
1
|
-
|
2
|
-
{
|
3
|
-
{%-
|
4
|
-
{%- assign
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
149
|
-
let
|
168
|
+
let tStarts = liveShow[i].dataset.start.split(',');
|
169
|
+
let tEnds = liveShow[i].dataset.end.split(',');
|
150
170
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
liveShow[i].classList.
|
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
|
163
|
-
let
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
liveHide[i].classList.
|
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,98 +307,151 @@
|
|
281
307
|
};
|
282
308
|
|
283
309
|
{% if site.conference.live.streaming -%}
|
284
|
-
{
|
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
|
298
|
-
let
|
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
|
306
|
-
|
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
|
-
|
309
|
-
|
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
|
314
|
-
|
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
|
-
|
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
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
-
|
329
|
-
|
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
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
389
|
+
if (!freezeTime) {
|
390
|
+
streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomStart - streamPrepend*60) * 1000, roomName);
|
391
|
+
}
|
392
|
+
}
|
335
393
|
|
336
|
-
|
337
|
-
|
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." }}');
|
397
|
+
|
398
|
+
if (!freezeTime && demo) {
|
399
|
+
streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd - streamPrepend*60) * 1000, roomName);
|
400
|
+
}
|
338
401
|
}
|
339
|
-
|
340
|
-
|
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
|
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 (
|
354
|
-
|
355
|
-
|
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
|
-
streamModal.find('#stream-info-color').
|
445
|
+
streamModal.find('#stream-info-color').removeClass(function (index, className) {
|
446
|
+
return (className.match(/(^|\s)border-soft-\S+/g) || []).join(' ');
|
447
|
+
});
|
448
|
+
streamModal.find('#stream-info-color').addClass('border-soft-' + talkNext.color);
|
370
449
|
|
371
|
-
streamModal.find('#stream-info-talk').text(
|
450
|
+
streamModal.find('#stream-info-talk').text(talkNext.name).attr('href', talkNext.href);
|
372
451
|
|
373
452
|
let speakerStr = '';
|
374
|
-
for (var i = 0; i <
|
375
|
-
let speaker = speakers[
|
453
|
+
for (var i = 0; i < talkNext.speakers.length; i++) {
|
454
|
+
let speaker = data.speakers[talkNext.speakers[i]];
|
376
455
|
if (speaker.href == '') {
|
377
456
|
speakerStr += speaker.name +', '
|
378
457
|
}
|
@@ -386,35 +465,37 @@
|
|
386
465
|
streamModal.find('#stream-info').removeClass('d-none');
|
387
466
|
|
388
467
|
if (!freezeTime) {
|
389
|
-
streamInfoTimer = setTimeout(setStreamInfo, delayStart(
|
468
|
+
streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.end) * 1000, roomName);
|
390
469
|
}
|
391
470
|
}
|
392
471
|
else {
|
393
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
|
+
}
|
394
483
|
}
|
395
484
|
};
|
396
485
|
|
397
486
|
let setStream = function (roomName) {
|
398
487
|
streamModal.find('.modal-footer .btn').removeClass('active');
|
399
|
-
streamModal.find('#stream-select').
|
488
|
+
streamModal.find('#stream-select').val(0);
|
400
489
|
|
490
|
+
// Recover room name in case of empty default
|
401
491
|
let room = getRoom(roomName);
|
402
492
|
roomName = room.name;
|
403
|
-
let tNow = time();
|
404
493
|
|
405
|
-
|
406
|
-
preStartStream(roomName);
|
407
|
-
}
|
408
|
-
else if (tNow > room.end) {
|
409
|
-
postEndStream(roomName);
|
410
|
-
}
|
411
|
-
else {
|
412
|
-
activeStream(roomName);
|
413
|
-
}
|
494
|
+
setStreamVideo(roomName);
|
414
495
|
setStreamInfo(roomName);
|
415
496
|
|
416
497
|
streamModal.find('#stream-button' + room.id).addClass('active');
|
417
|
-
streamModal.find('#stream-select').
|
498
|
+
streamModal.find('#stream-select').val(room.id);
|
418
499
|
};
|
419
500
|
|
420
501
|
let updateStream = function () {
|
@@ -429,8 +510,8 @@
|
|
429
510
|
};
|
430
511
|
|
431
512
|
let stopUpdateStream = function () {
|
432
|
-
if (typeof
|
433
|
-
clearInterval(
|
513
|
+
if (typeof streamVideoTimer !== "undefined") {
|
514
|
+
clearInterval(streamVideoTimer);
|
434
515
|
}
|
435
516
|
if (typeof streamInfoTimer !== "undefined") {
|
436
517
|
clearInterval(streamInfoTimer);
|
@@ -446,6 +527,7 @@
|
|
446
527
|
let setupStream = function () {
|
447
528
|
streamModal = $('#stream-modal');
|
448
529
|
|
530
|
+
// configure modal opening buttons
|
449
531
|
streamModal.on('show.bs.modal', function (event) {
|
450
532
|
let button = $(event.relatedTarget);
|
451
533
|
let roomName = button.data('room');
|
@@ -455,6 +537,7 @@
|
|
455
537
|
hideModal(event);
|
456
538
|
});
|
457
539
|
|
540
|
+
// configure room selection buttons in modal
|
458
541
|
streamModal.find('.modal-footer .btn').on('click', function(event) {
|
459
542
|
event.preventDefault();
|
460
543
|
|
@@ -462,12 +545,18 @@
|
|
462
545
|
setStream(roomName);
|
463
546
|
});
|
464
547
|
|
548
|
+
// configure room selection menu in modal
|
465
549
|
streamModal.find('#stream-select').on('change', function(event) {
|
466
550
|
event.preventDefault();
|
467
551
|
|
468
552
|
let roomName = $(this).children('option:selected').text();
|
469
553
|
setStream(roomName);
|
470
554
|
});
|
555
|
+
|
556
|
+
// load data
|
557
|
+
$.getJSON('{{ site.baseurl }}/assets/js/data.json', function(json) {
|
558
|
+
data = json;
|
559
|
+
});
|
471
560
|
};
|
472
561
|
|
473
562
|
let setup = function () {
|