jekyll-theme-conference 2.3.1 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c720f58e937e6ff0aed3eee7e9107c09d8c23d5b0baa5724c54a23cacb33ee4b
4
- data.tar.gz: 5e7b98cde919f1a3dd6290b46d287ea73565bf0d40927f82fa6ecce00cc52044
3
+ metadata.gz: 0ebb94e878ab7f234d64b2a45c45153438c9e075251d9dda31bc12e670168f91
4
+ data.tar.gz: '0980a8034943452466ce56df8e81a76b4e0f1bb9f2d66fa9ad7a8028157cf6b8'
5
5
  SHA512:
6
- metadata.gz: ed80869f7fc9dbb226ccfee9e4eb3c537e64dd3f0a9db674afb24cb48dffd4b50e31be01c50bbd635493de0c4490388c52fba0cb88119fedaabeadd487e89951
7
- data.tar.gz: 7058af0d31c5b99356d5c33707df521c3858759aa3180143fd8d1d2ca3ddefb7b9a3349f320366071709d0737206ecffecb78bacddd2f06a4a02779a57a6b652
6
+ metadata.gz: dfb07d4cad799e4c8e1d2742966b5dce78d586e2d73b359f6f5b8cffd6aacc7f8b510dbadeec3af407f92cd9801eae12edff14240ec81621e8c86de0abc77e93
7
+ data.tar.gz: b2381ce0e3e608130c37f55695e3c27af9980f3097359b6989ecb257bad158611bbfc00b61464835b48a3aadb9144e31077a3e4778ee6f746c953a1f20269bd0
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
- There exists a Python file in this repository, `create_entries.py`, which can be used to import content from 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.
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.
112
+
113
+ ### Automatic Build
106
114
 
107
- 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 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:
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:
108
116
 
109
- - `workflows.example.yml` -> `.github/workflows.main.yml`
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.
@@ -183,10 +201,6 @@ conference:
183
201
 
184
202
  The navigation bar is located at the top and visible on every site. On the right it show the title of the website (`site.title`) followed by the links listed under the `links` property of the `navigation` property. See the _Content_ > _Links_ section below for the available properties per link.
185
203
 
186
- Additionally, a navigation bar link can also have the following properties:
187
-
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).
189
-
190
204
  Example:
191
205
 
192
206
  ```yaml
@@ -195,6 +209,7 @@ conference:
195
209
  links:
196
210
  - name: Program
197
211
  relative_url: /program/
212
+ - live: true
198
213
  - name: Previous Editions
199
214
  menu:
200
215
  - name: 2020 (current)
@@ -224,7 +239,7 @@ conference:
224
239
 
225
240
  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
241
 
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:
242
+ 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
243
 
229
244
  - a `img` property specifying the path to the image file relative to the `/assets/images/` folder.
230
245
 
@@ -286,7 +301,31 @@ conference:
286
301
  Try again next year.
287
302
  ```
288
303
 
289
- ### Talk Settings: Main Categories and Icons
304
+ ### Live Indications & Streaming
305
+
306
+ 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).
307
+
308
+ 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
+
310
+ In order to activate the functionality the `live` property has to be set containing
311
+
312
+ - the date of the day at which the conference takes place (`date`),
313
+ - the timezone in which the conference takes place (`timezone`),
314
+ - optionally if streaming is enabled (`streaming`) with indications how many minutes early the stream will begin and end, and
315
+ - 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
+
317
+ ```yaml
318
+ conference:
319
+ live:
320
+ date: 01.01.2020
321
+ timezone: GMT+1
322
+ streaming:
323
+ start_early: 15 # in minutes
324
+ end_late: 0 # in minutes
325
+ demo: false
326
+ ```
327
+
328
+ ### Talk Settings
290
329
 
291
330
  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
331
 
@@ -314,11 +353,12 @@ conference:
314
353
  color: info
315
354
  - name: Cat B
316
355
  color: success
356
+
317
357
  # Hide icons on talk overview page
318
358
  hide_icons: false
319
359
  ```
320
360
 
321
- ### Speaker Settings: First name
361
+ ### Speaker Settings
322
362
 
323
363
  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
364
 
@@ -330,7 +370,7 @@ conference:
330
370
  show_firstname: false
331
371
  ```
332
372
 
333
- ### Location Settings: Hide all and configure map
373
+ ### Location Settings
334
374
 
335
375
  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
376
  In order to hide all rooms add the `hide: true` setting (default: `false`) to the `location` property.
@@ -353,7 +393,7 @@ conference:
353
393
  map_provider: "OpenStreetMap.Mapnik"
354
394
  ```
355
395
 
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.
396
+ 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
397
 
358
398
  Example:
359
399
 
@@ -364,11 +404,13 @@ Example:
364
404
  {% include js/conference.js %}
365
405
 
366
406
  (function() {
407
+ let map = window.conference.map;
408
+
367
409
  if (typeof map !== 'undefined') {
368
410
  var main_station = L.marker([47.37785, 8.54035], {
369
411
  icon: L.divIcon({
370
412
  className: '',
371
- html: '<span class="fas fa-train"></span> Bahnhof Zürich',
413
+ html: '<span class="fas fa-train"></span> Main Station',
372
414
  iconSize: [120, 56]
373
415
  })
374
416
  }).addTo(map);
@@ -454,8 +496,9 @@ Each speaker is represented by a file in the `_speakers/` directory. It must beg
454
496
 
455
497
  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
498
 
457
- - the room's `name`, and
458
- - optionally `hide: true` if the room's page should not be linked to.
499
+ - the room's `name`
500
+ - optionally `hide: true` if the room's page should not be linked to, and
501
+ - optionally a URL pointing to a live stream for the given room during the conference (`live`, see the section _Live Indications & Streaming_ above).
459
502
 
460
503
  ### Links
461
504
 
@@ -471,6 +514,11 @@ Links are used at different location throughout the theme: They can either be us
471
514
  + pointing to a file uploaded to the `/documents` folder (for talks `/documents/slides`, for speakers `/documents/bio`): `file:`
472
515
  + pointing to an external video: `video:`
473
516
 
517
+ Additionally, a navigation bar or main landing page link can also have the following properties:
518
+
519
+ - `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).
521
+
474
522
  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.
475
523
 
476
524
  Example:
@@ -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();