diff --git a/README.md b/README.md
index e3477a82..6d2b1ae7 100644
--- a/README.md
+++ b/README.md
@@ -503,11 +503,11 @@ Example:
{% include js/conference.js %}
-(function() {
- let map = window.conference.map;
+(() => {
+ const map = window.conference.map;
if (typeof map !== 'undefined') {
- var main_station = L.marker([47.37785, 8.54035], {
+ let main_station = L.marker([47.37785, 8.54035], {
icon: L.divIcon({
className: '',
html: ' Main Station',
diff --git a/_includes/js/conference.js b/_includes/js/conference.js
index a037d54a..7e963d9b 100644
--- a/_includes/js/conference.js
+++ b/_includes/js/conference.js
@@ -1,13 +1,19 @@
-// Global app variable
-window.conference = {};
-
-// Bootstrap (Style Framework)
+// Libraries
+// Bootstrap (Style Framework)
{% include js/lib/jquery-3.5.1.min.js %}
{% include js/lib/popper.min.js %}
{% include js/lib/bootstrap.js %}
-// FontAwesome (Icons)
-// Imported via CSS and webfonts
+// FontAwesome (Icons)
+// Imported via CSS and webfonts
+
+// Conference
+window.conference = {
+ config: {
+ baseurl: '{{ site.baseurl }}'
+ }
+};
+
// Program
{% include js/lib/syncscroll.js %}
@@ -31,3 +37,6 @@ window.conference = {};
{% if site.conference.live %}
{% include js/live.js %}
{% endif %}
+
+// Load configuration and start initialization
+{% include js/init.js %}
diff --git a/_includes/js/init.js b/_includes/js/init.js
new file mode 100644
index 00000000..abcd6c2c
--- /dev/null
+++ b/_includes/js/init.js
@@ -0,0 +1,37 @@
+const init = () => {
+ // Load configuration
+ const request = new Request(window.conference.config.baseurl + '/assets/js/config.json');
+
+ fetch(request)
+ .then(response =>
+ response.json()
+ )
+ .then(config => {
+ // Add configuration to global scope
+ window.conference.config = Object.assign(window.conference.config, config);
+
+ // Execute initialization functions
+ for (const [name, module] of Object.entries(window.conference)) {
+ if (name == 'config') {
+ continue;
+ }
+
+ let c;
+ if (name in config) {
+ c = config[name];
+ }
+ let l;
+ if (name in config.lang) {
+ l = config.lang[name];
+ }
+
+ module.init(c, l)
+ }
+
+ })
+ .catch((error) => {
+ console.log(error);
+ });
+};
+
+init();
diff --git a/_includes/js/live.js b/_includes/js/live.js
index 87a98124..c52bad4f 100644
--- a/_includes/js/live.js
+++ b/_includes/js/live.js
@@ -1,74 +1,77 @@
-window.conference.live = (function() {
- {% assign d = site.data.program.days | first -%}
- {%- include partials/get_day_time.html -%}
- {%- assign t = day_start_talk -%}
+window.conference.live = (() => {
+ let config;
+ let lang;
- {%- include partials/get_talk_timestamp.html -%}
- {%- assign conf_start = timestamp_start -%}
-
- {%- assign d = site.data.program.days | last -%}
- {%- include partials/get_day_time.html -%}
- {%- assign t = day_end_talk -%}
+ let data;
- {%- include partials/get_talk_timestamp.html -%}
- {%- assign conf_end = timestamp_end -%}
+ let confStart;
+ let confEnd;
+ let confDur;
- let data;
+ let stream;
+ let streamPause;
+ let streamPrepend;
+ let streamExtend;
- const confStart = {{ conf_start }};
- const confEnd = {{ conf_end }};
- const confDur = confEnd - confStart;
+ let demo;
+ let demoStart;
+ let demoEnd;
+ let demoDur;
+ let demoPause;
let freezeTime = false;
let timeFrozen = 0;
let timeOffset = 0;
- let demo = {{ site.conference.live.demo.enable | default: "false" }};
- let demoDur = {{ site.conference.live.demo.duration | default: 300 }};
- let demoPause = {{ site.conference.live.demo.pause | default: 10 }};
- let demoStart = confStart - confDur/demoDur*demoPause;
- let demoEnd = confEnd + confDur/demoDur*demoPause;
-
let liveTimer;
let streamVideoTimer;
let streamInfoTimer;
- const loadData = function () {
- // Fetch schedule from external file
- $.getJSON('{{ site.baseurl }}/assets/js/data.json', function(json) {
- data = json;
+ const loadData = () => {
+ // Load schedule
+ const request = new Request(window.conference.config.baseurl + '/assets/js/data.json');
+
+ fetch(request)
+ .then(response =>
+ response.json()
+ )
+ .then(d => {
+ data = d;
+ })
+ .catch((error) => {
+ console.log(error);
});
};
- const getData = function () {
+ const getData = () => {
// Return data
return data;
};
- const mod = function (n, m) {
+ const mod = (n, m) => {
// Absolute modulo
return ((n % m) + m) % m;
};
- const timeNow = function () {
+ const timeNow = () => {
// Current timestamp in seconds
return Math.floor(Date.now() / 1000);
};
- const timeCont = function () {
+ const timeCont = () => {
// Continuous time (respecting previous pauses)
return timeNow() - timeOffset;
};
- const timeCycle = function () {
+ const timeCycle = () => {
// Cyclic timestamp in seconds
- let actTime = timeNow();
- let relTime = mod(actTime, demoDur + 2*demoPause) / (demoDur + 2*demoPause);
- let cycleTime = mod((demoEnd - demoStart) * relTime - timeOffset, (demoEnd - demoStart)) + demoStart;
+ const actTime = timeNow();
+ const relTime = mod(actTime, demoDur + 2*demoPause) / (demoDur + 2*demoPause);
+ const cycleTime = mod((demoEnd - demoStart) * relTime - timeOffset, (demoEnd - demoStart)) + demoStart;
return cycleTime;
};
- const time = function () {
+ const time = () => {
// Return app time
if (freezeTime) {
return timeFrozen;
@@ -81,7 +84,7 @@ window.conference.live = (function() {
}
};
- const pauseTime = function () {
+ const pauseTime = () => {
// Pause app time
if (!freezeTime) {
timeFrozen = time();
@@ -91,7 +94,7 @@ window.conference.live = (function() {
}
};
- const continueTime = function () {
+ const continueTime = () => {
// Continue app time
if (freezeTime) {
freezeTime = false;
@@ -100,7 +103,7 @@ window.conference.live = (function() {
}
};
- const resetTime = function () {
+ const resetTime = () => {
// Reset app time
timeOffset = 0;
freezeTime = false;
@@ -108,12 +111,12 @@ window.conference.live = (function() {
startUpdate();
};
- const setTime = function (newTime, newDay) {
+ const setTime = (newTime, newDay) => {
// Set and pause app time
pauseTime();
let dayIdx;
- if (arguments.length < 2) {
+ if (!newDay) {
dayIdx = 0;
}
else if (Number.isInteger(newDay)) {
@@ -125,7 +128,7 @@ window.conference.live = (function() {
else {
dayIdx = data.days.find(o => o.name === newDay);
}
- let newDate = data.days[dayIdx].date;
+ const newDate = data.days[dayIdx].date;
let d = new Date(newDate);
newTime = newTime.split(':');
@@ -136,19 +139,19 @@ window.conference.live = (function() {
update();
};
- const getTime = function () {
+ const getTime = () => {
// Return app time as string
- let tConvert = time();
+ const tConvert = time();
- let d = new Date(tConvert * 1000);
- let dStr = d.toISOString().slice(0,10);
- let h = d.getHours();
- let m = d.getMinutes();
+ const d = new Date(tConvert * 1000);
+ const dStr = d.toISOString().slice(0,10);
+ const h = d.getHours();
+ const m = d.getMinutes();
return dStr +" "+ h +":"+ (m < 10 ? "0" : "") + m;
};
- const timeUnit = function () {
+ const timeUnit = () => {
// App time refresh rate
if (demo) {
return 0.1;
@@ -158,10 +161,10 @@ window.conference.live = (function() {
}
};
- const delayStart = function (startTime) {
+ const delayStart = (startTime) => {
// Seconds until given startTime occurs
- let tNow = time();
- let tUnit = timeUnit();
+ const tNow = time();
+ const tUnit = timeUnit();
if (demo) {
// Convert virtual duration to real duration
@@ -178,7 +181,7 @@ window.conference.live = (function() {
}
};
- let model = {
+ const model = {
set demo(value) {
demo = value;
resetTime();
@@ -188,18 +191,18 @@ window.conference.live = (function() {
}
};
- const updateLive = function () {
+ const updateLive = () => {
// Update status all live elements in DOM
- let tNow = time();
- let liveShow = document.getElementsByClassName('live-show');
- let liveHide = document.getElementsByClassName('live-hide');
- let liveTime = document.getElementsByClassName('live-time');
- let livePast = document.getElementsByClassName('live-past');
+ const tNow = time();
+ const liveShow = document.getElementsByClassName('live-show');
+ const liveHide = document.getElementsByClassName('live-hide');
+ const liveTime = document.getElementsByClassName('live-time');
+ const livePast = document.getElementsByClassName('live-past');
// Show elements for a given period
for (let i = 0; i < liveShow.length; i++) {
- let tStarts = liveShow[i].dataset.start.split(',');
- let tEnds = liveShow[i].dataset.end.split(',');
+ const tStarts = liveShow[i].dataset.start.split(',');
+ const tEnds = liveShow[i].dataset.end.split(',');
for (let k = 0; k < tStarts.length; k++) {
if (tNow >= tStarts[k] && tNow < tEnds[k]) {
@@ -216,8 +219,8 @@ window.conference.live = (function() {
// Hide elements for a given period
for (let i = 0; i < liveHide.length; i++) {
- let tStarts = liveHide[i].dataset.start.split(',');
- let tEnds = liveHide[i].dataset.end.split(',');
+ const tStarts = liveHide[i].dataset.start.split(',');
+ const tEnds = liveHide[i].dataset.end.split(',');
for (let k = 0; k < tStarts.length; k++) {
if (tNow >= tStarts[k] && tNow < tEnds[k]) {
@@ -236,7 +239,7 @@ window.conference.live = (function() {
// Update duration string for given elements
for (let i = 0; i < liveTime.length; i++) {
- let t = liveTime[i].dataset.time;
+ const t = liveTime[i].dataset.time;
if (typeof t == "undefined") {
break;
}
@@ -244,17 +247,17 @@ window.conference.live = (function() {
let tStr;
if (tRel >= -60 && tRel < 0) {
- tStr = '{{ site.data.lang[site.conference.lang].live.time.soon | default: "soon" }}';
+ tStr = lang.time.soon;
}
else if (tRel >= 0 && tRel < 60) {
- tStr = '{{ site.data.lang[site.conference.lang].live.time.now | default: "now" }}';
+ tStr = lang.time.now;
}
else {
if (tRel < 0) {
- tStr = '{{ site.data.lang[site.conference.lang].live.time.in | default: "in" }} ';
+ tStr = lang.time.in;
}
else {
- tStr = '{{ site.data.lang[site.conference.lang].live.time.since | default: "since" }} ';
+ tStr = lang.time.since;
}
tRel = Math.abs(tRel);
@@ -266,28 +269,28 @@ window.conference.live = (function() {
break;
}
else if (dWeeks > 1) {
- tStr += dWeeks +' {{ site.data.lang[site.conference.lang].live.time.weeks | default: "weeks" }}';
+ tStr += dWeeks +' '+ lang.time.weeks;
}
else if (dWeeks == 1) {
- tStr += '1 {{ site.data.lang[site.conference.lang].live.time.week | default: "week" }}';
+ tStr += '1 '+ lang.time.week;
}
else if (dDays > 1) {
- tStr += dDays +' {{ site.data.lang[site.conference.lang].live.time.days | default: "days" }}';
+ tStr += dDays +' '+ lang.time.days;
}
else if (dDays == 1) {
- tStr += '1 {{ site.data.lang[site.conference.lang].live.time.day | default: "day" }}';
+ tStr += '1 '+ lang.time.day;
}
else if (dHours > 1) {
- tStr += dHours +' {{ site.data.lang[site.conference.lang].live.time.hours | default: "hours" }}';
+ tStr += dHours +' '+ lang.time.hours;
}
else if (dHours == 1) {
- tStr += '1 {{ site.data.lang[site.conference.lang].live.time.hour | default: "hour" }}';
+ tStr += '1 '+ lang.time.hour;
}
else if (dMins > 1) {
- tStr += dMins +' {{ site.data.lang[site.conference.lang].live.time.minutes | default: "minutes" }}';
+ tStr += dMins +' '+ lang.time.minutes;
}
else {
- tStr += '1 {{ site.data.lang[site.conference.lang].live.time.minute | default: "minute" }}';
+ tStr += '1 '+ lang.time.minute;
}
}
@@ -296,7 +299,7 @@ window.conference.live = (function() {
// Disable elements for a given period
for (let i = 0; i < livePast.length; i++) {
- let t = livePast[i].dataset.time;
+ const t = livePast[i].dataset.time;
if (typeof t == "undefined") {
break;
}
@@ -320,7 +323,7 @@ window.conference.live = (function() {
}
};
- const startUpdateLive = function () {
+ const startUpdateLive = () => {
// Start update timer to update live elements in DOM
stopUpdateLive();
updateLive();
@@ -330,377 +333,377 @@ window.conference.live = (function() {
liveTimer = setInterval(updateLive, timeUnit() * 1000);
}
else {
- setTimeout(function() {
+ setTimeout(() => {
liveTimer = setInterval(updateLive, timeUnit() * 1000);
updateLive();
}, delayStart(confStart) * 1000);
}
};
- const stopUpdateLive = function () {
+ const stopUpdateLive = () => {
// stopUpdate update timer to update live elements in DOM
if (typeof liveTimer !== "undefined") {
clearInterval(liveTimer);
}
};
- {% if site.conference.live.streaming.enable -%}
- const streamPause = {{ site.conference.live.streaming.time_pause | default: 60 }}; // in minutes
- const streamPrepend = {{ site.conference.live.streaming.time_prepend | default: 5 }}; // in minutes
- const streamExtend = {{ site.conference.live.streaming.time_extend | default: 5 }}; // in minutes
+ let streamModal;
- let streamModal;
+ const getRoom = (roomName) => {
+ // Return room object for given room name
+ if (roomName in data.rooms) {
+ return data.rooms[roomName];
+ }
+ else {
+ return data.rooms[Object.keys(data.rooms)[0]];
+ }
+ };
- const getRoom = function (roomName) {
- // Return room object for given room name
- if (roomName in data.rooms) {
- return data.rooms[roomName];
- }
- else {
- return data.rooms[Object.keys(data.rooms)[0]];
- }
- };
+ const getTalks = (roomName) => {
+ if (roomName in data.talks) {
+ return data.talks[roomName];
+ }
+ else {
+ return false;
+ }
+ };
- const getTalks = function (roomName) {
- if (roomName in data.talks) {
- return data.talks[roomName];
- }
- else {
- return false;
- }
- };
-
- const getNextTalk = function (roomName) {
- // Get talk object for next talk in given room
- let timeNow = time();
- let talksHere = getTalks(roomName);
-
- if (talksHere) {
- if (timeNow < talksHere[talksHere.length-1].end) {
- for (var i = 0; i < talksHere.length; i++) {
- if (timeNow < talksHere[i].end) {
- return talksHere[i];
- }
+ const getNextTalk = (roomName) => {
+ // Get talk object for next talk in given room
+ const timeNow = time();
+ const talksHere = getTalks(roomName);
+
+ if (talksHere) {
+ if (timeNow < talksHere[talksHere.length-1].end) {
+ for (let i = 0; i < talksHere.length; i++) {
+ if (timeNow < talksHere[i].end) {
+ return talksHere[i];
}
}
}
- return false;
- };
-
- const getNextPause = function (roomName) {
- // Get time object for next pause in given room
- let timeNow = time();
- let talksHere = getTalks(roomName);
-
- if (talksHere) {
- if (timeNow < talksHere[talksHere.length-1].end) {
- for (var i = 1; i < talksHere.length; i++) {
- if (timeNow < talksHere[i].start && streamPause*60 <= talksHere[i].start - talksHere[i-1].end) {
- return {
- 'start': talksHere[i-1].end,
- 'end': talksHere[i].start,
- };
- }
+ }
+ return false;
+ };
+
+ const getNextPause = (roomName) => {
+ // Get time object for next pause in given room
+ const timeNow = time();
+ const talksHere = getTalks(roomName);
+
+ if (talksHere) {
+ if (timeNow < talksHere[talksHere.length-1].end) {
+ for (let i = 1; i < talksHere.length; i++) {
+ if (timeNow < talksHere[i].start && streamPause*60 <= talksHere[i].start - talksHere[i-1].end) {
+ return {
+ 'start': talksHere[i-1].end,
+ 'end': talksHere[i].start,
+ };
}
}
}
- return false;
- };
-
- const setStreamIframeContent = function (content) {
- // Set stream modal iframe to show given text
- streamModal.find('iframe').attr('src', '');
- streamModal.find('iframe').addClass('d-none');
- streamModal.find('#stream-placeholder > div').text(content);
- streamModal.find('#stream-placeholder').addClass('d-flex');
- };
-
- const setStreamIframeSrc = function (href) {
- // Set stream modal iframe to show given URL
- streamModal.find('iframe').attr('src', href);
- streamModal.find('#stream-placeholder').addClass('d-none').removeClass('d-flex');
- streamModal.find('iframe').removeClass('d-none');
- };
-
- const setStreamVideo = function (roomName) {
- // Update stream modal iframe:
- // Show stream with start/pause/end message (for given room) and keep updated
- let timeNow = time();
-
- let talksHere = getTalks(roomName);
- let roomStart, roomEnd;
- if (talksHere) {
- roomStart = talksHere[0].start;
- roomEnd = talksHere[talksHere.length-1].end;
- }
- else {
- // If no program for given room, take overall first and last talk
- roomStart = 0;
- roomEnd = 0;
- for (let roomNameTalk in data.talks) {
- talksHere = getTalks(roomNameTalk);
- let crntRoomStart = talksHere[0].start;
- let crntRoomEnd = talksHere[talksHere.length-1].end;
-
- if (roomStart == 0 || roomStart > crntRoomStart) {
- roomStart = crntRoomStart;
- }
- if (roomEnd == 0 || roomEnd < crntRoomEnd) {
- roomEnd = crntRoomEnd;
- }
+ }
+ return false;
+ };
+
+ const setStreamIframeContent = (content) => {
+ // Set stream modal iframe to show given text
+ streamModal.find('iframe').attr('src', '');
+ streamModal.find('iframe').addClass('d-none');
+ streamModal.find('#stream-placeholder > div').text(content);
+ streamModal.find('#stream-placeholder').addClass('d-flex');
+ };
+
+ const setStreamIframeSrc = (href) => {
+ // Set stream modal iframe to show given URL
+ streamModal.find('iframe').attr('src', href);
+ streamModal.find('#stream-placeholder').addClass('d-none').removeClass('d-flex');
+ streamModal.find('iframe').removeClass('d-none');
+ };
+
+ const setStreamVideo = (roomName) => {
+ // Update stream modal iframe:
+ // Show stream with start/pause/end message (for given room) and keep updated
+ const timeNow = time();
+
+ const talksHere = getTalks(roomName);
+ let roomStart, roomEnd;
+ if (talksHere) {
+ roomStart = talksHere[0].start;
+ roomEnd = talksHere[talksHere.length-1].end;
+ }
+ else {
+ // If no program for given room, take overall first and last talk
+ roomStart = 0;
+ roomEnd = 0;
+ for (let roomNameTalk in data.talks) {
+ talksHere = getTalks(roomNameTalk);
+ const crntRoomStart = talksHere[0].start;
+ const crntRoomEnd = talksHere[talksHere.length-1].end;
+
+ if (roomStart == 0 || roomStart > crntRoomStart) {
+ roomStart = crntRoomStart;
+ }
+ if (roomEnd == 0 || roomEnd < crntRoomEnd) {
+ roomEnd = crntRoomEnd;
}
}
+ }
- if (typeof streamVideoTimer !== "undefined") {
- clearInterval(streamVideoTimer);
+ if (typeof streamVideoTimer !== "undefined") {
+ clearInterval(streamVideoTimer);
+ }
+
+ // Conference not yet started
+ if (timeNow < roomStart - streamPrepend*60) {
+ setStreamIframeContent(lang.pre_stream);
+
+ if (!freezeTime) {
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomStart - streamPrepend*60) * 1000, roomName);
}
+ }
- // Conference not yet started
- if (timeNow < roomStart - streamPrepend*60) {
- setStreamIframeContent('{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}');
+ // Conference is over
+ else if (timeNow > roomEnd + streamExtend*60) {
+ setStreamIframeContent(lang.post_stream);
- if (!freezeTime) {
- streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomStart - streamPrepend*60) * 1000, roomName);
- }
+ if (!freezeTime && demo) {
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd - streamPrepend*60) * 1000, roomName);
}
+ }
+
+ // Conference ongoing
+ else {
+ const pauseNext = getNextPause(roomName);
- // Conference is over
- else if (timeNow > roomEnd + streamExtend*60) {
- setStreamIframeContent('{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}');
+ // Currently stream is paused
+ if (pauseNext && timeNow >= pauseNext.start + streamExtend*60 && timeNow <= pauseNext.end - streamPrepend*60) {
+ setStreamIframeContent(lang.pause_stream);
- if (!freezeTime && demo) {
- streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd - streamPrepend*60) * 1000, roomName);
+ if (!freezeTime) {
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.end - streamPrepend*60) * 1000, roomName);
}
}
-
- // Conference ongoing
+ // Currently a talk is active
else {
- let pauseNext = getNextPause(roomName);
+ const room = getRoom(roomName);
+ setStreamIframeSrc(room.href);
- // Currently stream is paused
- if (pauseNext && timeNow >= pauseNext.start + streamExtend*60 && timeNow <= pauseNext.end - streamPrepend*60) {
- setStreamIframeContent('{{ site.data.lang[site.conference.lang].live.pause_stream | default: "Live stream is currently paused." }}');
-
- if (!freezeTime) {
- streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.end - streamPrepend*60) * 1000, roomName);
+ if (!freezeTime) {
+ if (pauseNext) {
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.start + streamExtend*60) * 1000, roomName);
}
- }
- // Currently a talk is active
- else {
- let room = getRoom(roomName);
- setStreamIframeSrc(room.href);
-
- if (!freezeTime) {
- if (pauseNext) {
- streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.start + streamExtend*60) * 1000, roomName);
- }
- else {
- streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd + streamExtend*60) * 1000, roomName);
- }
+ else {
+ streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd + streamExtend*60) * 1000, roomName);
}
}
}
- };
+ }
+ };
- const setStreamInfo = function (roomName) {
- // Update stream modal info bar:
- // Show next talk and speaker (for given room) and keep updated
- let timeNow = time();
- let talkNext = getNextTalk(roomName);
+ const setStreamInfo = (roomName) => {
+ // Update stream modal info bar:
+ // Show next talk and speaker (for given room) and keep updated
+ const timeNow = time();
+ const talkNext = getNextTalk(roomName);
- if (typeof streamInfoTimer !== "undefined") {
- clearInterval(streamInfoTimer);
- }
+ if (typeof streamInfoTimer !== "undefined") {
+ clearInterval(streamInfoTimer);
+ }
- if (talkNext && timeNow >= talkNext.start - streamPause*60) {
- document.getElementById('stream-info').dataset.time = talkNext.start;
- document.getElementById('stream-info-time').dataset.time = talkNext.start;
- updateLive();
+ if (talkNext && timeNow >= talkNext.start - streamPause*60) {
+ document.getElementById('stream-info').dataset.time = talkNext.start;
+ document.getElementById('stream-info-time').dataset.time = talkNext.start;
+ updateLive();
- streamModal.find('#stream-info-color').removeClass(function (index, className) {
- return (className.match(/(^|\s)border-soft-\S+/g) || []).join(' ');
- });
- streamModal.find('#stream-info-color').addClass('border-soft-' + talkNext.color);
+ streamModal.find('#stream-info-color').removeClass((index, className) => {
+ return (className.match(/(^|\s)border-soft-\S+/g) || []).join(' ');
+ });
+ streamModal.find('#stream-info-color').addClass('border-soft-' + talkNext.color);
- streamModal.find('#stream-info-talk').text(talkNext.name).attr('href', talkNext.href);
+ streamModal.find('#stream-info-talk').text(talkNext.name).attr('href', talkNext.href);
- let speakerStr = '';
- for (let i = 0; i < talkNext.speakers.length; i++) {
- let speaker = data.speakers[talkNext.speakers[i]];
- if (speaker.href == '') {
- speakerStr += speaker.name +', '
- }
- else {
- speakerStr += ''+ speaker.name +', ';
- }
- }
- speakerStr = speakerStr.slice(0, -2);
- streamModal.find('#stream-info-speakers').html(speakerStr);
-
- if (talkNext.live_links) {
- let linksStr = '';
- for (let i = 0; i < talkNext.live_links.length; i++) {
- const link = talkNext.live_links[i];
-
- linksStr += '';
- if (link.icon) {
- linksStr += ' ';
- }
- linksStr += link.name + '';
- }
- streamModal.find('#stream-info-links').html(linksStr).removeClass('d-none');
+ let speakerStr = '';
+ for (let i = 0; i < talkNext.speakers.length; i++) {
+ let speaker = data.speakers[talkNext.speakers[i]];
+ if (speaker.href == '') {
+ speakerStr += speaker.name +', '
}
else {
- streamModal.find('#stream-info-links').addClass('d-none');
+ speakerStr += ''+ speaker.name +', ';
}
+ }
+ speakerStr = speakerStr.slice(0, -2);
+ streamModal.find('#stream-info-speakers').html(speakerStr);
- streamModal.find('#stream-info').removeClass('d-none');
+ if (talkNext.live_links) {
+ let linksStr = '';
+ for (let i = 0; i < talkNext.live_links.length; i++) {
+ const link = talkNext.live_links[i];
- if (!freezeTime) {
- streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.end) * 1000, roomName);
+ linksStr += '';
+ if (link.icon) {
+ linksStr += ' ';
+ }
+ linksStr += link.name + '';
}
+ streamModal.find('#stream-info-links').html(linksStr).removeClass('d-none');
}
else {
- streamModal.find('#stream-info').addClass('d-none');
+ streamModal.find('#stream-info-links').addClass('d-none');
+ }
- if (!freezeTime) {
- if (talkNext) {
- streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.start - streamPause*60) * 1000, roomName);
- }
- else if (demo) {
- let talksHere = getTalks(roomName);
- if (talksHere) {
- streamInfoTimer = setTimeout(setStreamInfo, delayStart(talksHere[0].start - streamPrepend*60) * 1000, roomName);
- }
+ streamModal.find('#stream-info').removeClass('d-none');
+
+ if (!freezeTime) {
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.end) * 1000, roomName);
+ }
+ }
+ else {
+ streamModal.find('#stream-info').addClass('d-none');
+
+ if (!freezeTime) {
+ if (talkNext) {
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.start - streamPause*60) * 1000, roomName);
+ }
+ else if (demo) {
+ let talksHere = getTalks(roomName);
+ if (talksHere) {
+ streamInfoTimer = setTimeout(setStreamInfo, delayStart(talksHere[0].start - streamPrepend*60) * 1000, roomName);
}
}
}
- };
+ }
+ };
- const setStream = function (roomName) {
- // Update stream modal (iframe and info bar) for given room
- streamModal.find('.modal-footer .btn').removeClass('active');
- streamModal.find('#stream-select').val(0);
+ const setStream = (roomName) => {
+ // Update stream modal (iframe and info bar) for given room
+ streamModal.find('.modal-footer .btn').removeClass('active');
+ streamModal.find('#stream-select').val(0);
- // Recover room name in case of empty default
- let room = getRoom(roomName);
- roomName = room.name;
+ // Recover room name in case of empty default
+ const room = getRoom(roomName);
+ roomName = room.name;
- setStreamVideo(roomName);
- setStreamInfo(roomName);
+ setStreamVideo(roomName);
+ setStreamInfo(roomName);
- streamModal.find('#stream-button' + room.id).addClass('active');
- streamModal.find('#stream-select').val(room.id);
- };
+ streamModal.find('#stream-button' + room.id).addClass('active');
+ streamModal.find('#stream-select').val(room.id);
+ };
- const updateStream = function () {
- // Update stream modal for currently active room button
- if (streamModal.hasClass('show')) {
- let activeButton = streamModal.find('.modal-footer .btn.active');
- let roomName = activeButton.data('room');
+ const updateStream = () => {
+ // Update stream modal for currently active room button
+ if (streamModal.hasClass('show')) {
+ let activeButton = streamModal.find('.modal-footer .btn.active');
+ let roomName = activeButton.data('room');
- if (typeof roomName !== "undefined") {
- setStream(roomName);
- }
+ if (typeof roomName !== "undefined") {
+ setStream(roomName);
}
- };
+ }
+ };
- const stopUpdateStream = function () {
- // Stop stream modal update timer
- if (typeof streamVideoTimer !== "undefined") {
- clearInterval(streamVideoTimer);
- }
- if (typeof streamInfoTimer !== "undefined") {
- clearInterval(streamInfoTimer);
- }
- };
-
- const hideModal = function () {
- // Close stream modal
- streamModal.find('iframe').attr('src', '');
- streamModal.find('.modal-footer .btn').removeClass('active');
- streamModal.find('#stream-select').selectedIndex = -1;
- };
-
- const setupStream = function () {
- // Setup events when modal opens/closes
- streamModal = $('#stream-modal');
-
- // configure modal opening buttons
- streamModal.on('show.bs.modal', function (event) {
- let button = $(event.relatedTarget);
- let roomName = button.data('room');
- setStream(roomName);
- });
- streamModal.on('hide.bs.modal', function () {
- hideModal();
- });
+ const stopUpdateStream = () => {
+ // Stop stream modal update timer
+ if (typeof streamVideoTimer !== "undefined") {
+ clearInterval(streamVideoTimer);
+ }
+ if (typeof streamInfoTimer !== "undefined") {
+ clearInterval(streamInfoTimer);
+ }
+ };
- // configure room selection buttons in modal
- streamModal.find('.modal-footer .btn').on('click', function(event) {
- event.preventDefault();
+ const hideModal = () => {
+ // Close stream modal
+ streamModal.find('iframe').attr('src', '');
+ streamModal.find('.modal-footer .btn').removeClass('active');
+ streamModal.find('#stream-select').selectedIndex = -1;
+ };
- let roomName = $(this).data('room');
- setStream(roomName);
- });
+ const setupStream = () => {
+ // Setup events when modal opens/closes
+ streamModal = $('#stream-modal');
- // configure room selection menu in modal
- streamModal.find('#stream-select').on('change', function(event) {
- event.preventDefault();
+ // configure modal opening buttons
+ streamModal.on('show.bs.modal', (event) => {
+ let button = $(event.relatedTarget);
+ let roomName = button.data('room');
+ setStream(roomName);
+ });
+ streamModal.on('hide.bs.modal', () => {
+ hideModal();
+ });
- let roomName = $(this).children('option:selected').text();
- setStream(roomName);
- });
- };
+ // configure room selection buttons in modal
+ streamModal.find('.modal-footer .btn').on('click', function (event) {
+ event.preventDefault();
- const setup = function () {
- loadData();
- startUpdateLive();
- setupStream();
- };
+ let roomName = $(this).data('room');
+ setStream(roomName);
+ });
- const update = function () {
- updateLive();
- updateStream();
- };
+ // configure room selection menu in modal
+ streamModal.find('#stream-select').on('change', function (event) {
+ event.preventDefault();
- const startUpdate = function () {
- startUpdateLive();
- updateStream();
- };
+ let roomName = $(this).children('option:selected').text();
+ setStream(roomName);
+ });
+ };
- const stopUpdate = function () {
- stopUpdateLive();
- stopUpdateStream();
- };
+ const init = (c, l) => {
+ config = c;
+ lang = l;
- {%- else -%}
+ confStart = config.time.start;
+ confEnd = config.time.end;
+ confDur = confEnd - confStart;
- const setup = function () {
- loadData();
- startUpdateLive();
- };
+ demo = config.demo.enable;
+ demoDur = config.demo.duration;
+ demoPause = config.demo.pause;
+ demoStart = confStart - confDur/demoDur*demoPause;
+ demoEnd = confEnd + confDur/demoDur*demoPause;
- const update = function () {
- updateLive();
- };
+ stream = config.streaming.enable;
+ streamPause = config.streaming.pause;
+ streamPrepend = config.streaming.prepend;
+ streamExtend = config.streaming.extend;
+
+ loadData();
+ startUpdateLive();
+ if (stream) {
+ setupStream();
+ }
+ };
- const startUpdate = function () {
- startUpdateLive();
- };
+ const update = () => {
+ updateLive();
+ if (stream) {
+ updateStream();
+ }
+ };
- const stopUpdate = function () {
- stopUpdateLive();
- };
+ const startUpdate = () => {
+ startUpdateLive();
+ if (stream) {
+ updateStream();
+ }
+ };
- {%- endif %}
+ const stopUpdate = () => {
+ stopUpdateLive();
+ if (stream) {
+ stopUpdateStream();
+ }
+ };
return {
- init: setup,
+ init: init,
getData: getData,
pauseTime: pauseTime,
@@ -713,5 +716,3 @@ window.conference.live = (function() {
};
})();
-
-window.conference.live.init();
diff --git a/_includes/js/map.js b/_includes/js/map.js
index 1298bf9d..92bb08f1 100644
--- a/_includes/js/map.js
+++ b/_includes/js/map.js
@@ -1,45 +1,38 @@
-window.conference.mapConfig = (function() {
+window.conference.mapConfig = (() => {
+ let config;
+ let lang;
let map;
- let mapProvider = "{{ site.conference.map.map_provider | default: 'OpenStreetMap.Mapnik' }}";
- let homeCoord = [{{ site.conference.map.home_coord }}];
- let zoomLevel = {{ site.conference.map.default_zoom | default: 17 }};
+ const setup = (elId) => {
+ map = L.map(elId).setView(config.map.home_coord, config.map.default_zoom);
- let setup = function (elId) {
- map = L.map(elId).setView(homeCoord, zoomLevel);
+ L.tileLayer.provider(config.map.map_provider).addTo(map);
- L.tileLayer.provider(mapProvider).addTo(map);
-
- L.easyButton('far fa-star', function(){
- map.flyTo(homeCoord, zoomLevel);
- }, '{{ site.data.lang[site.conference.lang].location.focus_conf | default: "Center map on conference location" }}').addTo(map);
+ L.easyButton('far fa-star', () => {
+ map.flyTo(config.map.home_coord, config.map.default_zoom);
+ }, lang.location.focus_conf).addTo(map);
L.control.locate({
flyTo: true,
strings: {
- title: '{{ site.data.lang[site.conference.lang].location.focus_me | default: "Show me where I am" }}'
+ title: lang.location.focus_me
}
}).addTo(map);
};
- let init = function () {
- let elId = 'map';
+ const init = (c, l) => {
+ config = c;
+ lang = l;
+
+ const elId = 'map';
if (document.getElementById(elId)) {
setup(elId);
- window.conference.map = map;
}
};
return {
- init: init,
- default: {
- mapProvider: mapProvider,
- homeCoord: homeCoord,
- zoomLevel: zoomLevel
- }
+ init: init
};
})();
-
-window.conference.mapConfig.init();
diff --git a/_includes/js/modal.js b/_includes/js/modal.js
index 4134a7d9..f09b542e 100644
--- a/_includes/js/modal.js
+++ b/_includes/js/modal.js
@@ -1,15 +1,15 @@
-window.conference.modal = (function () {
+window.conference.modal = (() => {
- let show = function (el, event) {
- let button = $(event.relatedTarget);
+ const show = (el, event) => {
+ const button = $(event.relatedTarget);
- let href = button.data('href');
- let format = button.data('format');
- let title = button.data('title');
- let subtitle = button.data('subtitle');
- let footer = button.data('footer');
+ const href = button.data('href');
+ const format = button.data('format');
+ const title = button.data('title');
+ const subtitle = button.data('subtitle');
+ const footer = button.data('footer');
- let modal = $(el);
+ const modal = $(el);
modal.find('iframe').attr('src', href);
if (title) {
@@ -51,8 +51,8 @@ window.conference.modal = (function () {
}
};
- let hide = function (el) {
- let modal = $(el);
+ const hide = (el) => {
+ const modal = $(el);
modal.find('.modal-title h3').text('');
modal.find('.modal-title h5').text('').addClass('d-none');
@@ -60,8 +60,8 @@ window.conference.modal = (function () {
modal.find('.modal-footer p').html('');
};
- let init = function() {
- let elSel = '#link-modal';
+ const init = () => {
+ const elSel = '#link-modal';
$(elSel).on('show.bs.modal', function (event) {
show(this, event);
@@ -76,5 +76,3 @@ window.conference.modal = (function () {
};
})();
-
-window.conference.modal.init();
diff --git a/_includes/js/program.js b/_includes/js/program.js
index a65aa14d..50d6829f 100644
--- a/_includes/js/program.js
+++ b/_includes/js/program.js
@@ -1,27 +1,25 @@
-window.conference.program = (function() {
- let updateHash = function (hash) {
- let scrollPosition = $('body').scrollTop() || $('html').scrollTop();
+window.conference.program = (() => {
+ const updateHash = (hash) => {
+ const scrollPosition = document.documentElement.scrollTop;
window.location.hash = hash;
- $('html,body').scrollTop(scrollPosition);
+ document.documentElement.scrollTop = scrollPosition;
};
- let init = function () {
+ const init = () => {
if ($('#day-list')) {
// Switch to day if page load with hash
- var hash = window.location.hash;
+ const hash = window.location.hash;
if (hash) {
$('#day-list a[href="' + hash + '"]').tab('show');
}
+
// Switch to day if today
else {
- let d = new Date();
- let dStr = d.getFullYear() +"-"+ (d.getMonth()+1) +"-"+ d.getDate()
- // since a timezone compensation is added when passed as string, today's date has also
- // to be passed as string (as it is done below)
- let today = new Date(dStr);
+ let today = new Date();
+ today.setHours(0,0,0,0);
$('a[data-toggle="tab"]').each(function () {
- let d = new Date($(this).data('date'));
+ const d = new Date($(this).data('date'));
if (today.getTime() === d.getTime()) {
$(this).tab('show');
@@ -41,5 +39,3 @@ window.conference.program = (function() {
init: init
};
})();
-
-window.conference.program.init();
diff --git a/_layouts/config.html b/_layouts/config.html
new file mode 100644
index 00000000..337b3e24
--- /dev/null
+++ b/_layouts/config.html
@@ -0,0 +1,78 @@
+{
+ {%- include partials/get_enable_map.html -%}
+ {%- if enable_map %}
+ "map": {
+ "map_provider": "{{ site.conference.map.map_provider | default: 'OpenStreetMap.Mapnik' }}",
+ "home_coord": [{{ site.conference.map.home_coord }}],
+ "default_zoom": {{ site.conference.map.default_zoom | default: 17 }}
+ },
+ {%- endif %}
+
+ {% if site.conference.live -%}
+ "live": {
+ "time": {
+ {% assign d = site.data.program.days | first -%}
+ {%- include partials/get_day_time.html -%}
+ {%- assign t = day_start_talk -%}
+
+ {%- include partials/get_talk_timestamp.html -%}
+ {%- assign conf_start = timestamp_start -%}
+
+ {%- assign d = site.data.program.days | last -%}
+ {%- include partials/get_day_time.html -%}
+ {%- assign t = day_end_talk -%}
+
+ {%- include partials/get_talk_timestamp.html -%}
+ {%- assign conf_end = timestamp_end -%}
+
+ "start": {{ conf_start }},
+ "end": {{ conf_end }}
+ },
+
+ "streaming": {
+ "enable": {{ site.conference.live.streaming.enable | default: "false" }},
+ "pause": {{ site.conference.live.streaming.time_pause | default: 60 }},
+ "prepend": {{ site.conference.live.streaming.time_prepend | default: 5 }},
+ "extend": {{ site.conference.live.streaming.time_extend | default: 5 }}
+ },
+
+ "demo": {
+ "enable": {{ site.conference.live.demo.enable | default: "false" }},
+ "duration": {{ site.conference.live.demo.duration | default: 300 }},
+ "pause": {{ site.conference.live.demo.pause | default: 10 }}
+ }
+ },
+ {%- endif %}
+
+ "lang": {
+ {%- if enable_map %}
+ "map": {
+ "focus_conf": "{{ site.data.lang[site.conference.lang].location.focus_conf | default: "Center map on conference location" }}",
+ "focus_me": "{{ site.data.lang[site.conference.lang].location.focus_me | default: "Show me where I am" }}"
+ }
+ {%- endif -%}
+
+ {%- if site.conference.live and site.conference.live.streaming.enable -%}
+ {%- if enable_map %},{% endif %}
+ "live": {
+ "pre_stream": "{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}",
+ "post_stream": "{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}",
+ "pause_stream": "{{ site.data.lang[site.conference.lang].live.pause_stream | default: "Live stream is currently paused." }}",
+ "time": {
+ "soon": "{{ site.data.lang[site.conference.lang].live.time.soon | default: "soon" }}",
+ "now": "{{ site.data.lang[site.conference.lang].live.time.now | default: "now" }}",
+ "in": "{{ site.data.lang[site.conference.lang].live.time.in | default: "in" }} ",
+ "since": "{{ site.data.lang[site.conference.lang].live.time.since | default: "since" }} ",
+ "weeks": "{{ site.data.lang[site.conference.lang].live.time.weeks | default: "weeks" }}",
+ "week": "{{ site.data.lang[site.conference.lang].live.time.week | default: "week" }}",
+ "days": "{{ site.data.lang[site.conference.lang].live.time.days | default: "days" }}",
+ "day": "{{ site.data.lang[site.conference.lang].live.time.day | default: "day" }}",
+ "hours": "{{ site.data.lang[site.conference.lang].live.time.hours | default: "hours" }}",
+ "hour": "{{ site.data.lang[site.conference.lang].live.time.hour | default: "hour" }}",
+ "minutes": "{{ site.data.lang[site.conference.lang].live.time.minutes | default: "minutes" }}",
+ "minute": "{{ site.data.lang[site.conference.lang].live.time.minute | default: "minute" }}"
+ }
+ }
+ {%- endif %}
+ }
+}
diff --git a/_layouts/data.html b/_layouts/data.html
index 9a1374c4..858e91ce 100644
--- a/_layouts/data.html
+++ b/_layouts/data.html
@@ -1,5 +1,5 @@
-{% if site.conference.live and site.conference.live.streaming.enable -%}
{
+ {% if site.conference.live and site.conference.live.streaming.enable -%}
"days": [
{%- for d in site.data.program.days %}
{
@@ -116,5 +116,6 @@
{%- endunless -%}
{%- endfor %}
}
+
+ {%- endif %}
}
-{%- endif -%}
diff --git a/assets/js/config.json b/assets/js/config.json
new file mode 100644
index 00000000..6562a1e1
--- /dev/null
+++ b/assets/js/config.json
@@ -0,0 +1,3 @@
+---
+layout: config
+---
diff --git a/jekyll-theme-conference.gemspec b/jekyll-theme-conference.gemspec
index 71d59d54..0a38d56a 100644
--- a/jekyll-theme-conference.gemspec
+++ b/jekyll-theme-conference.gemspec
@@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "jekyll-theme-conference"
- spec.version = "3.4.1"
+ spec.version = "3.5.0"
spec.authors = ["Lorenz Schmid"]
spec.email = ["lorenzschmid@users.noreply.github.com"]