jekyll-theme-conference 2.3.0 → 2.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -13
- data/_includes/js/conference-live.js +415 -0
- data/_includes/js/conference-map.js +37 -11
- data/_includes/js/conference-modal.js +38 -17
- data/_includes/js/conference.js +9 -1
- data/_includes/partials/checks.html +8 -3
- data/_includes/partials/footer.html +6 -2
- data/_includes/partials/get_conf_time.html +54 -0
- data/_includes/partials/get_link.html +24 -4
- data/_includes/partials/get_timestamp.html +4 -0
- data/_includes/partials/header.html +13 -0
- data/_includes/partials/live-modal.html +37 -0
- data/_includes/partials/live_button.html +19 -0
- data/_includes/partials/navbar.html +30 -0
- data/_includes/partials/navbar_rooms.html +1 -1
- data/_includes/partials/show_room.html +1 -1
- data/_includes/partials/show_talk_duration.html +1 -1
- data/_includes/partials/show_talk_time.html +1 -1
- data/_layouts/delete_hidden.html +25 -0
- data/_layouts/location.html +1 -1
- data/_layouts/program.html +10 -50
- data/_layouts/room.html +12 -6
- data/_layouts/speaker-overview.html +1 -1
- data/_layouts/speaker.html +12 -8
- data/_layouts/talk-overview.html +13 -6
- data/_layouts/talk.html +26 -12
- data/_sass/conference.scss +23 -22
- data/assets/icons/live.svg +81 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a6617ea192ab16d014da7430f23276860d7ecce37cdd591815103bb086efb65
|
4
|
+
data.tar.gz: a31e631388e20578008dcef761e416a5a53c53166b068ecb410ee0f75b1f9196
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef931eb98d10bc467358f2948e76b15ac8d11a8abe1d7528688a5f672fcb8127a31cbe46165f41b355d58d186ca83a5d010d5b5cb0abfb41f685296c908421ae
|
7
|
+
data.tar.gz: a3ef7ee1df36b5280534f5819d10c21c2447f9430650e89d0aa4923243656d51d4e2483c888adfe2e30cfb18b0e0d40584add7dc4c3449ba997d604d1f6b9684
|
data/README.md
CHANGED
@@ -89,6 +89,10 @@ The different talks, speakers and rooms are stored as a collection of files. Eac
|
|
89
89
|
|
90
90
|
The actual schedule defining when and in which room a talk takes place is stored as a [YAML data file](https://jekyllrb.com/docs/datafiles/) under `_data/program.yml`. For further details about it see below in the section _Content_.
|
91
91
|
|
92
|
+
:warning: Please note that the generated website can be quite large containing many unnecessary whitespaces. It is recommended to minimize the generated output files before uploading them to a server (e.g. with [minify](https://github.com/tdewolff/minify)).
|
93
|
+
|
94
|
+
### Jump Start
|
95
|
+
|
92
96
|
In order to be up and running simply use the default content of this repository as an initial base for your new website. After having setup a new Jekyll website copy the following files and folders into the website's folder:
|
93
97
|
|
94
98
|
- `_config.example.yml` -> `_config.yml`
|
@@ -102,11 +106,23 @@ In order to be up and running simply use the default content of this repository
|
|
102
106
|
- `speakers/`
|
103
107
|
- `talks/`
|
104
108
|
|
105
|
-
|
109
|
+
### Automatic Import
|
110
|
+
|
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 based on it. Just open your terminal and type `python create_entries.py --help` to show the help and get started.
|
106
112
|
|
107
|
-
|
113
|
+
### Automatic Build
|
108
114
|
|
109
|
-
|
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 an example Github Action configuration file which automatically builds and minimizes the website upon adding a new tag. It then attaches the generated website as package to a release for easy downloading. Simply copy the following file to your repository and adapt it to your needs:
|
116
|
+
|
117
|
+
- `workflow-example.yml` -> `.github/workflows/main.yml`
|
118
|
+
|
119
|
+
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 Github Action workflow to delete the files.
|
120
|
+
|
121
|
+
```markdown
|
122
|
+
---
|
123
|
+
layout: delete_hidden
|
124
|
+
---
|
125
|
+
```
|
110
126
|
|
111
127
|
|
112
128
|
## Configuration
|
@@ -124,6 +140,8 @@ conference:
|
|
124
140
|
show_errors: false
|
125
141
|
```
|
126
142
|
|
143
|
+
:warning: Please be sure to disable this parameter for your production system.
|
144
|
+
|
127
145
|
### Collection URLs
|
128
146
|
|
129
147
|
The three required collections containing the files for the talks, speakers and rooms have to be specified in the `_config.yml` file. The first block declares them and sets the URL under which they will later be accessed. The second block defines the default layout for each of the collection.
|
@@ -165,7 +183,7 @@ _Note:_ While you might want to change the URLs, the name of the three collectio
|
|
165
183
|
|
166
184
|
### Language
|
167
185
|
|
168
|
-
In order to adapt the language of the theme set the `lang` property.
|
186
|
+
In order to adapt the language of the theme set the `lang` property. If you change it from its default, make sure you have copied the internationalization file from this repository to `_data/lang.yml`. Currently the following languages are included:
|
169
187
|
|
170
188
|
- English: `en` (Default)
|
171
189
|
- German: `de`
|
@@ -185,7 +203,8 @@ The navigation bar is located at the top and visible on every site. On the right
|
|
185
203
|
|
186
204
|
Additionally, a navigation bar link can also have the following properties:
|
187
205
|
|
188
|
-
- `menu` containing another list of links. This creates a dropdown menu of multiple sublinks. The sublinks have the same properties as regular links (see the _Content_ > _Links_ section)
|
206
|
+
- `menu` containing another list of links. This creates a dropdown menu of multiple sublinks. The sublinks have the same properties as regular links (see the _Content_ > _Links_ section), or
|
207
|
+
- `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_ below).
|
189
208
|
|
190
209
|
Example:
|
191
210
|
|
@@ -195,6 +214,7 @@ conference:
|
|
195
214
|
links:
|
196
215
|
- name: Program
|
197
216
|
relative_url: /program/
|
217
|
+
- live: true
|
198
218
|
- name: Previous Editions
|
199
219
|
menu:
|
200
220
|
- name: 2020 (current)
|
@@ -224,7 +244,7 @@ conference:
|
|
224
244
|
|
225
245
|
The main landing page is shown at the root of the website to greet new visitors. In order to show it you need to create a `index.md` file in the root of your website's folder and specify its layout as `layout: main`. The remaining customizations are specified in the `_config.yml` file.
|
226
246
|
|
227
|
-
The main page states your site's title (`site.title`) or a logo instead. The logo can be configured through the `logo` property under the `main` property containing
|
247
|
+
The main page states your site's title (`site.title`) or a logo instead. The logo can be configured through the `logo` property under the `main` property containing
|
228
248
|
|
229
249
|
- a `img` property specifying the path to the image file relative to the `/assets/images/` folder.
|
230
250
|
|
@@ -286,7 +306,31 @@ conference:
|
|
286
306
|
Try again next year.
|
287
307
|
```
|
288
308
|
|
289
|
-
###
|
309
|
+
### Live Indications & Streaming
|
310
|
+
|
311
|
+
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).
|
312
|
+
|
313
|
+
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).
|
314
|
+
|
315
|
+
In order to activate the functionality the `live` property has to be set containing
|
316
|
+
|
317
|
+
- the date of the day at which the conference takes place (`date`),
|
318
|
+
- the timezone in which the conference takes place (`timezone`),
|
319
|
+
- optionally if streaming is enabled (`streaming`) with indications how many minutes early the stream will begin and end, and
|
320
|
+
- optionally a demo mode setting, whereby the JavaScript function cycles through the entire program in five minutes for demonstration purposes (`demo: true`, default: `false`).
|
321
|
+
|
322
|
+
```yaml
|
323
|
+
conference:
|
324
|
+
live:
|
325
|
+
date: 01.01.2020
|
326
|
+
timezone: GMT+1
|
327
|
+
streaming:
|
328
|
+
start_early: 15 # in minutes
|
329
|
+
end_late: 0 # in minutes
|
330
|
+
demo: false
|
331
|
+
```
|
332
|
+
|
333
|
+
### Talk Settings
|
290
334
|
|
291
335
|
Each talk can have one or multiple categories associated via FrontMatter (see the _Individual Pages: Talks_ section below for more details). Some of these categories can be elevated to so called main categories". These are used to color group the talks across the entire website, particularly in the program. In order to do so add the `main_categories` property under the `talks` property. It consists of a list of all main categories. Each main category consists of:
|
292
336
|
|
@@ -314,11 +358,12 @@ conference:
|
|
314
358
|
color: info
|
315
359
|
- name: Cat B
|
316
360
|
color: success
|
361
|
+
|
317
362
|
# Hide icons on talk overview page
|
318
363
|
hide_icons: false
|
319
364
|
```
|
320
365
|
|
321
|
-
### Speaker Settings
|
366
|
+
### Speaker Settings
|
322
367
|
|
323
368
|
In the program as well as the speaker's overview the speaker's first name can be abbreviated to its first letter. Of course, you also have the option to not specify a first name for each speaker in the first place. In order to shorten the first name add the `show_firstname: true` setting (default: `false`) to the `speakers` property.
|
324
369
|
|
@@ -330,7 +375,7 @@ conference:
|
|
330
375
|
show_firstname: false
|
331
376
|
```
|
332
377
|
|
333
|
-
### Location Settings
|
378
|
+
### Location Settings
|
334
379
|
|
335
380
|
In case the location of your rooms is obvious (e.g. on a campus) you can decide to disable the location page and links to all the rooms. You still need to create the different rooms as files in the `_rooms/` directory, since they are needed as a reference. But there will not be any link pointing to it (effectively hiding them).
|
336
381
|
In order to hide all rooms add the `hide: true` setting (default: `false`) to the `location` property.
|
@@ -353,7 +398,7 @@ conference:
|
|
353
398
|
map_provider: "OpenStreetMap.Mapnik"
|
354
399
|
```
|
355
400
|
|
356
|
-
The map is based on the JavaScript Library [Leaflet](https://leafletjs.com/) and can be customized by editing the `assets/js/main.js` file, e.g. adding additional layers with markers, text, or shapes to the map. To start, copy simply the file from this repository and make use of the initialized global variable `map` pointing to the Leaflet container.
|
401
|
+
The map is based on the JavaScript Library [Leaflet](https://leafletjs.com/) and can be customized by editing the `assets/js/main.js` file, e.g. adding additional layers with markers, text, or shapes to the map. To start, copy simply the file from this repository and make use of the initialized global variable `window.conference.map` pointing to the Leaflet container.
|
357
402
|
|
358
403
|
Example:
|
359
404
|
|
@@ -364,11 +409,13 @@ Example:
|
|
364
409
|
{% include js/conference.js %}
|
365
410
|
|
366
411
|
(function() {
|
412
|
+
let map = window.conference.map;
|
413
|
+
|
367
414
|
if (typeof map !== 'undefined') {
|
368
415
|
var main_station = L.marker([47.37785, 8.54035], {
|
369
416
|
icon: L.divIcon({
|
370
417
|
className: '',
|
371
|
-
html: '<span class="fas fa-train"></span>
|
418
|
+
html: '<span class="fas fa-train"></span> Main Station',
|
372
419
|
iconSize: [120, 56]
|
373
420
|
})
|
374
421
|
}).addTo(map);
|
@@ -454,8 +501,9 @@ Each speaker is represented by a file in the `_speakers/` directory. It must beg
|
|
454
501
|
|
455
502
|
Each room is represented by a file in the `_rooms/` directory. It must begin with valid [YAML Front Matter](https://jekyllrb.com/docs/frontmatter/) containing
|
456
503
|
|
457
|
-
- the room's `name
|
458
|
-
- optionally `hide: true` if the room's page should not be linked to
|
504
|
+
- the room's `name`
|
505
|
+
- optionally `hide: true` if the room's page should not be linked to, and
|
506
|
+
- optionally a URL pointing to a live stream for the given room during the conference (`live`, see the section _Live Indications & Streaming_ above).
|
459
507
|
|
460
508
|
### Links
|
461
509
|
|
@@ -0,0 +1,415 @@
|
|
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;
|
10
|
+
|
11
|
+
let freezeTime = false;
|
12
|
+
let timeFrozen = 0;
|
13
|
+
let timeOffset = 0;
|
14
|
+
|
15
|
+
let demo = {{ site.conference.live.demo | default: "false" }};
|
16
|
+
let durDemo = 5*60; // in seconds
|
17
|
+
let durPause = 10; // in seconds
|
18
|
+
|
19
|
+
let demoStart = confStart - confDur/durDemo*durPause;
|
20
|
+
let demoEnd = confEnd + confDur/durDemo*durPause;
|
21
|
+
|
22
|
+
let liveTimer;
|
23
|
+
let streamTimer;
|
24
|
+
|
25
|
+
let mod = function (n, m) {
|
26
|
+
return ((n % m) + m) % m;
|
27
|
+
};
|
28
|
+
|
29
|
+
let timeNow = function () {
|
30
|
+
return Math.floor(Date.now() / 1000);
|
31
|
+
};
|
32
|
+
|
33
|
+
let timeCont = function () {
|
34
|
+
return timeNow() - timeOffset;
|
35
|
+
};
|
36
|
+
|
37
|
+
let timeCycle = function () {
|
38
|
+
let actTime = timeNow();
|
39
|
+
let relTime = mod(actTime, durDemo + 2*durPause) / durDemo;
|
40
|
+
let cycleTime = mod((demoEnd - demoStart) * relTime - timeOffset, (demoEnd - demoStart)) + demoStart;
|
41
|
+
return cycleTime;
|
42
|
+
};
|
43
|
+
|
44
|
+
let time = function () {
|
45
|
+
if (freezeTime) {
|
46
|
+
return timeFrozen;
|
47
|
+
}
|
48
|
+
else if (demo) {
|
49
|
+
return timeCycle();
|
50
|
+
}
|
51
|
+
else {
|
52
|
+
return timeCont();
|
53
|
+
}
|
54
|
+
};
|
55
|
+
|
56
|
+
let pauseTime = function () {
|
57
|
+
if (!freezeTime) {
|
58
|
+
timeFrozen = time();
|
59
|
+
freezeTime = true;
|
60
|
+
|
61
|
+
stopUpdate();
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
65
|
+
let continueTime = function () {
|
66
|
+
if (freezeTime) {
|
67
|
+
freezeTime = false;
|
68
|
+
timeOffset += time() - timeFrozen;
|
69
|
+
startUpdate();
|
70
|
+
}
|
71
|
+
};
|
72
|
+
|
73
|
+
let resetTime = function (timeStr) {
|
74
|
+
timeOffset = 0;
|
75
|
+
freezeTime = false;
|
76
|
+
|
77
|
+
startUpdate();
|
78
|
+
};
|
79
|
+
|
80
|
+
let setTime = function (newTime) {
|
81
|
+
pauseTime();
|
82
|
+
|
83
|
+
let d = new Date(confStart * 1000);
|
84
|
+
newTime = newTime.split(':');
|
85
|
+
d.setHours(newTime[0], newTime[1]);
|
86
|
+
|
87
|
+
timeFrozen = Math.floor(d.getTime() / 1000);
|
88
|
+
|
89
|
+
update();
|
90
|
+
};
|
91
|
+
|
92
|
+
let getTime = function (tConvert = time()) {
|
93
|
+
let d = new Date(tConvert * 1000);
|
94
|
+
let h = d.getHours();
|
95
|
+
let m = d.getMinutes();
|
96
|
+
|
97
|
+
return h + ":" + (m < 10 ? "0" : "") + m;
|
98
|
+
};
|
99
|
+
|
100
|
+
let timeUnit = function () {
|
101
|
+
if (demo) {
|
102
|
+
return 0.1;
|
103
|
+
}
|
104
|
+
else {
|
105
|
+
return 60;
|
106
|
+
}
|
107
|
+
};
|
108
|
+
|
109
|
+
let delayStart = function (startTime) {
|
110
|
+
let tNow = time();
|
111
|
+
let tUnit = timeUnit();
|
112
|
+
|
113
|
+
if (demo) {
|
114
|
+
// Convert virtual duration to real duration
|
115
|
+
return mod(startTime - tNow, demoEnd - demoStart) / (demoEnd - demoStart) * (durDemo + 2*durPause);
|
116
|
+
}
|
117
|
+
else {
|
118
|
+
if (startTime > tNow) {
|
119
|
+
return startTime - tNow;
|
120
|
+
}
|
121
|
+
else {
|
122
|
+
// Start on the unit
|
123
|
+
return (tUnit - (tNow % tUnit));
|
124
|
+
}
|
125
|
+
}
|
126
|
+
};
|
127
|
+
|
128
|
+
let toggleDemo = function () {
|
129
|
+
demo = !demo;
|
130
|
+
resetTime();
|
131
|
+
};
|
132
|
+
|
133
|
+
let demoOn = function () {
|
134
|
+
return demo;
|
135
|
+
};
|
136
|
+
|
137
|
+
let updateLive = function () {
|
138
|
+
let tNow = time();
|
139
|
+
let liveShow = document.getElementsByClassName('live-show');
|
140
|
+
let liveHide = document.getElementsByClassName('live-hide');
|
141
|
+
|
142
|
+
for (let i = 0; i < liveShow.length; i++) {
|
143
|
+
let tStart = liveShow[i].dataset.start;
|
144
|
+
let tEnd = liveShow[i].dataset.end;
|
145
|
+
|
146
|
+
if (tNow >= tStart && tNow < tEnd) {
|
147
|
+
// Show when active
|
148
|
+
liveShow[i].classList.remove('d-none');
|
149
|
+
}
|
150
|
+
else if (!liveShow[i].classList.contains('d-none')) {
|
151
|
+
// Hide otherwise
|
152
|
+
liveShow[i].classList.add('d-none');
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
for (let i = 0; i < liveHide.length; i++) {
|
157
|
+
let tStart = liveHide[i].dataset.start;
|
158
|
+
let tEnd = liveHide[i].dataset.end;
|
159
|
+
|
160
|
+
if (tNow >= tStart && tNow < tEnd) {
|
161
|
+
// Hide when active
|
162
|
+
if (!liveHide[i].classList.contains('d-none')) {
|
163
|
+
liveHide[i].classList.add('d-none');
|
164
|
+
}
|
165
|
+
}
|
166
|
+
else {
|
167
|
+
// Show otherwise
|
168
|
+
liveHide[i].classList.remove('d-none');
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
if (tNow > confEnd && !demo) {
|
173
|
+
// Cancel timer after program is over
|
174
|
+
stopUpdateLive();
|
175
|
+
}
|
176
|
+
};
|
177
|
+
|
178
|
+
let startUpdateLive = function () {
|
179
|
+
stopUpdateLive();
|
180
|
+
updateLive();
|
181
|
+
|
182
|
+
if (demo) {
|
183
|
+
// Immediate start required since delayStart would wait for next wrap around
|
184
|
+
liveTimer = setInterval(updateLive, timeUnit() * 1000);
|
185
|
+
}
|
186
|
+
else {
|
187
|
+
setTimeout(function() {
|
188
|
+
liveTimer = setInterval(updateLive, timeUnit() * 1000);
|
189
|
+
updateLive();
|
190
|
+
}, delayStart(confStart) * 1000);
|
191
|
+
}
|
192
|
+
};
|
193
|
+
|
194
|
+
let stopUpdateLive = function () {
|
195
|
+
if (typeof liveTimer !== "undefined") {
|
196
|
+
clearInterval(liveTimer);
|
197
|
+
}
|
198
|
+
};
|
199
|
+
|
200
|
+
{% if site.conference.live.streaming -%}
|
201
|
+
|
202
|
+
let rooms = {
|
203
|
+
{%- for r in site.data.program -%}
|
204
|
+
{%- assign room = site.rooms | where: 'name', r.room | first -%}
|
205
|
+
{%- if room.live -%}
|
206
|
+
|
207
|
+
{%- assign t = r.talks | first -%}
|
208
|
+
{%- include partials/get_talk_time.html -%}
|
209
|
+
{%- assign time_start = talk_start -%}
|
210
|
+
{%- assign time_end = talk_end -%}
|
211
|
+
{%- include partials/get_timestamp.html -%}
|
212
|
+
|
213
|
+
{%- assign offset_start = site.conference.live.streaming.start_early | default: 0 -%}
|
214
|
+
{%- assign room_ts_start = offset_start | times: -60 | plus: timestamp_start -%}
|
215
|
+
|
216
|
+
{%- assign t = r.talks | last -%}
|
217
|
+
{%- include partials/get_talk_time.html -%}
|
218
|
+
{%- assign time_start = talk_start -%}
|
219
|
+
{%- assign time_end = talk_end -%}
|
220
|
+
{%- include partials/get_timestamp.html -%}
|
221
|
+
|
222
|
+
{%- assign offset_end = site.conference.live.streaming.end_late | default: 0 -%}
|
223
|
+
{%- assign room_ts_end = offset_end | times: 60 | plus: timestamp_end -%}
|
224
|
+
|
225
|
+
"{{ room.name }}": {
|
226
|
+
"id": {{ forloop.index }},
|
227
|
+
"href": "{{ room.live }}",
|
228
|
+
"start": {{ room_ts_start }},
|
229
|
+
"end": {{ room_ts_end }}
|
230
|
+
},
|
231
|
+
{%- endif -%}
|
232
|
+
{%- endfor -%}
|
233
|
+
};
|
234
|
+
|
235
|
+
let streamModal;
|
236
|
+
|
237
|
+
let getRoom = function (roomName) {
|
238
|
+
if (roomName in rooms) {
|
239
|
+
return rooms[roomName];
|
240
|
+
}
|
241
|
+
else {
|
242
|
+
return rooms[Object.keys(rooms)[0]];
|
243
|
+
}
|
244
|
+
};
|
245
|
+
|
246
|
+
let preStartStream = function (roomName) {
|
247
|
+
let room = getRoom(roomName);
|
248
|
+
|
249
|
+
streamModal.find('iframe').attr('src', '');
|
250
|
+
streamModal.find('iframe').addClass('d-none');
|
251
|
+
streamModal.find('#stream-placeholder > div').text('{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}');
|
252
|
+
streamModal.find('#stream-placeholder').addClass('d-flex');
|
253
|
+
|
254
|
+
stopUpdateStream();
|
255
|
+
if (!freezeTime) {
|
256
|
+
streamTimer = setTimeout(activeStream, delayStart(room.start) * 1000, roomName);
|
257
|
+
}
|
258
|
+
};
|
259
|
+
|
260
|
+
let activeStream = function (roomName) {
|
261
|
+
let room = getRoom(roomName);
|
262
|
+
|
263
|
+
streamModal.find('iframe').attr('src', room.href);
|
264
|
+
streamModal.find('#stream-placeholder').addClass('d-none').removeClass('d-flex');
|
265
|
+
streamModal.find('iframe').removeClass('d-none');
|
266
|
+
|
267
|
+
stopUpdateStream();
|
268
|
+
if (!freezeTime) {
|
269
|
+
streamTimer = setTimeout(postEndStream, delayStart(room.end) * 1000, roomName);
|
270
|
+
}
|
271
|
+
};
|
272
|
+
|
273
|
+
let postEndStream = function (roomName) {
|
274
|
+
let room = getRoom(roomName);
|
275
|
+
|
276
|
+
streamModal.find('iframe').attr('src', '');
|
277
|
+
streamModal.find('iframe').addClass('d-none');
|
278
|
+
streamModal.find('#stream-placeholder > div').text('{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}');
|
279
|
+
streamModal.find('#stream-placeholder').addClass('d-flex');
|
280
|
+
|
281
|
+
stopUpdateStream();
|
282
|
+
if (!freezeTime && demo) {
|
283
|
+
streamTimer = setTimeout(preStartStream, delayStart(demoStart) * 1000, roomName);
|
284
|
+
}
|
285
|
+
};
|
286
|
+
|
287
|
+
let setStream = function (roomName) {
|
288
|
+
streamModal.find('.modal-footer .btn').removeClass('active');
|
289
|
+
streamModal.find('#stream-select').selectedIndex = -1;
|
290
|
+
|
291
|
+
let room = getRoom(roomName);
|
292
|
+
let tNow = time();
|
293
|
+
|
294
|
+
if (tNow < room.start) {
|
295
|
+
preStartStream(roomName);
|
296
|
+
}
|
297
|
+
else if (tNow > room.end) {
|
298
|
+
postEndStream(roomName);
|
299
|
+
}
|
300
|
+
else {
|
301
|
+
activeStream(roomName);
|
302
|
+
}
|
303
|
+
|
304
|
+
streamModal.find('#stream-button' + room.id).addClass('active');
|
305
|
+
streamModal.find('#stream-select').selectedIndex = room.id;
|
306
|
+
};
|
307
|
+
|
308
|
+
let updateStream = function () {
|
309
|
+
if (streamModal.hasClass('show')) {
|
310
|
+
let activeButton = streamModal.find('.modal-footer .btn.active');
|
311
|
+
let roomName = activeButton.data('room');
|
312
|
+
|
313
|
+
if (typeof roomName !== "undefined") {
|
314
|
+
setStream(roomName);
|
315
|
+
}
|
316
|
+
}
|
317
|
+
};
|
318
|
+
|
319
|
+
let stopUpdateStream = function () {
|
320
|
+
if (typeof streamTimer !== "undefined") {
|
321
|
+
clearInterval(streamTimer);
|
322
|
+
}
|
323
|
+
};
|
324
|
+
|
325
|
+
let hideModal = function (event) {
|
326
|
+
streamModal.find('iframe').attr('src', '');
|
327
|
+
streamModal.find('.modal-footer .btn').removeClass('active');
|
328
|
+
streamModal.find('#stream-select').selectedIndex = -1;
|
329
|
+
};
|
330
|
+
|
331
|
+
let setupStream = function () {
|
332
|
+
streamModal = $('#stream-modal');
|
333
|
+
|
334
|
+
streamModal.on('show.bs.modal', function (event) {
|
335
|
+
let button = $(event.relatedTarget);
|
336
|
+
let roomName = button.data('room');
|
337
|
+
setStream(roomName);
|
338
|
+
});
|
339
|
+
streamModal.on('hide.bs.modal', function (event) {
|
340
|
+
hideModal(event);
|
341
|
+
});
|
342
|
+
|
343
|
+
streamModal.find('.modal-footer .btn').on('click', function(event) {
|
344
|
+
event.preventDefault();
|
345
|
+
|
346
|
+
let roomName = $(this).data('room');
|
347
|
+
setStream(roomName);
|
348
|
+
});
|
349
|
+
|
350
|
+
streamModal.find('#stream-select').on('change', function(event) {
|
351
|
+
event.preventDefault();
|
352
|
+
|
353
|
+
let roomName = $(this).children('option:selected').text();
|
354
|
+
setStream(roomName);
|
355
|
+
});
|
356
|
+
};
|
357
|
+
|
358
|
+
let setup = function () {
|
359
|
+
startUpdateLive();
|
360
|
+
setupStream();
|
361
|
+
};
|
362
|
+
|
363
|
+
let update = function () {
|
364
|
+
updateLive();
|
365
|
+
updateStream();
|
366
|
+
};
|
367
|
+
|
368
|
+
let startUpdate = function () {
|
369
|
+
startUpdateLive();
|
370
|
+
updateStream();
|
371
|
+
};
|
372
|
+
|
373
|
+
let stopUpdate = function () {
|
374
|
+
stopUpdateLive();
|
375
|
+
stopUpdateStream();
|
376
|
+
};
|
377
|
+
|
378
|
+
{%- else -%}
|
379
|
+
|
380
|
+
let setup = function () {
|
381
|
+
startUpdateLive();
|
382
|
+
};
|
383
|
+
|
384
|
+
let update = function () {
|
385
|
+
updateLive();
|
386
|
+
};
|
387
|
+
|
388
|
+
let startUpdate = function () {
|
389
|
+
startUpdateLive();
|
390
|
+
};
|
391
|
+
|
392
|
+
let stopUpdate = function () {
|
393
|
+
stopUpdateLive();
|
394
|
+
};
|
395
|
+
|
396
|
+
{%- endif %}
|
397
|
+
|
398
|
+
return {
|
399
|
+
init: setup,
|
400
|
+
|
401
|
+
pauseTime: pauseTime,
|
402
|
+
continueTime: continueTime,
|
403
|
+
resetTime: resetTime,
|
404
|
+
setTime: setTime,
|
405
|
+
getTime: getTime,
|
406
|
+
|
407
|
+
toggleDemo: toggleDemo,
|
408
|
+
demo: demoOn,
|
409
|
+
durDemo: durDemo,
|
410
|
+
durPause: durPause
|
411
|
+
};
|
412
|
+
|
413
|
+
})();
|
414
|
+
|
415
|
+
window.conference.live.init();
|