diff --git a/config.js b/config.js index be415b7..8f6d720 100644 --- a/config.js +++ b/config.js @@ -145,4 +145,4 @@ displaySystem.config({ }, //path to the modules, can even be a full url modulePath: "modules" -}); +}); \ No newline at end of file diff --git a/css/style.css b/css/style.css index 848127c..5f45a55 100644 --- a/css/style.css +++ b/css/style.css @@ -4,12 +4,18 @@ html, body { margin: 0; padding: 0; } + + + /* hides screen during initialization, overridden in themes */ + body { visibility: hidden; } + /* hides elements that are supposed to be hidden at least until theme is loaded and overrides the behavior */ + .hidden { visibility: hidden; } @@ -22,7 +28,9 @@ body { bottom: 0; } + /* control window */ + @media screen { body.controls { font-family: verdana, helvetica, sans-serif; @@ -41,8 +49,7 @@ body { display: inline-block; white-space: nowrap; } - body.controls input, - body.controls textarea { + body.controls input, body.controls textarea { width: 75px; border: 1px solid silver; border-right: none; @@ -56,4 +63,4 @@ body { body.controls button { margin-right: 4px; } -} +} \ No newline at end of file diff --git a/js/main.js b/js/main.js index 49a7622..8a18648 100644 --- a/js/main.js +++ b/js/main.js @@ -1,5 +1,5 @@ // display system main -var displaySystem = (function() { +var displaySystem = (function () { var system = {}; var config; var modules = {}; @@ -9,12 +9,12 @@ var displaySystem = (function() { function setConfig(_config) { config = _config; - setTimeout(init,0); + setTimeout(init, 0); } function prependToHead(el) { var h = document.getElementsByTagName('head')[0]; - h.insertBefore(el,h.firstChild); + h.insertBefore(el, h.firstChild); } function appendToHead(el) { @@ -22,14 +22,14 @@ var displaySystem = (function() { h.appendChild(el); } - function loadScript(src,onload) { + function loadScript(src, onload) { var el = document.createElement('script'); el.src = src; el.onload = onload; appendToHead(el); } - function loadCss(src,onLoad) { + function loadCss(src, onLoad) { var el = document.createElement('link'); el.rel = 'stylesheet'; el.href = src; @@ -48,13 +48,13 @@ var displaySystem = (function() { clearTimeout(pendingConnection); } if (window.location.protocol === 'https:') { - host = 'wss://'+config.wssHost; + host = 'wss://' + config.wssHost; } else { - host = 'ws://'+config.wsHost; + host = 'ws://' + config.wsHost; } ws = new WebSocket(host); - ws.onopen = function() { + ws.onopen = function () { if (config.mserverNode) { ws.send(JSON.stringify({ type: "subscribe", @@ -64,20 +64,20 @@ var displaySystem = (function() { backoff = 100; } }; - ws.onerror = function(e){ + ws.onerror = function (e) { console.log("error"); ws.close(); }; - ws.onclose = function() { - console.log("close reconnecting in",backoff,'ms'); + ws.onclose = function () { + console.log("close reconnecting in", backoff, 'ms'); connected = false; delete system.ws; - pendingConnection = setTimeout(function() { + pendingConnection = setTimeout(function () { connect(); - },backoff); - backoff = Math.min(maxBackoff,backoff * 2); + }, backoff); + backoff = Math.min(maxBackoff, backoff * 2); }; - ws.onmessage = function(msg) { + ws.onmessage = function (msg) { var data = JSON.parse(msg.data); if (data.topic) { handleMessage(data); @@ -99,7 +99,7 @@ var displaySystem = (function() { function getArguments(f) { var deps = f.toString().match(/^function\s*\w*\((.*?)\)/)[1]; - return deps?deps.split(/\s*,\s*/):[]; + return deps ? deps.split(/\s*,\s*/) : []; } var handlers = {}; @@ -113,37 +113,37 @@ var displaySystem = (function() { var module = modules[moduleName]; var api = module[action]; var args = getArguments(api); - var data = args.map(function(arg) { - return (msg.data||{})[arg]; + var data = args.map(function (arg) { + return (msg.data || {})[arg]; }); - api.apply(module,data); + api.apply(module, data); } //handle individual handlers if (handlers[topic]) { - handlers[topic].forEach(function(handler) { + handlers[topic].forEach(function (handler) { handler(msg); }); } } } - function sendMessage(def,action,data) { + function sendMessage(def, action, data) { if (config.wsHost || config.wssHost) { ws.send(JSON.stringify({ type: "publish", node: config.mserverNode, - topic: def.name+':'+action, + topic: def.name + ':' + action, data: data })); } } - function onMessage(def,action,handler) { + function onMessage(def, action, handler) { if (!def.name) { return; } - var topic = (def.name+':'+action); + var topic = (def.name + ':' + action); if (!handlers[topic]) { handlers[topic] = []; } @@ -153,14 +153,14 @@ var displaySystem = (function() { function init() { // initWebsocket(); connect(); - var modulePath = config.modulePath||'modules'; + var modulePath = config.modulePath || 'modules'; var pending = []; - Object.keys(config.modules).forEach(function(name,i) { - var src = modulePath+'/'+name+'.js'; + Object.keys(config.modules).forEach(function (name, i) { + var src = modulePath + '/' + name + '.js'; pending[i] = { name: name }; - loadScript(src,function() { + loadScript(src, function () { pending[i].def = lastModule; checkLoaded(pending); }); @@ -168,10 +168,10 @@ var displaySystem = (function() { } function checkLoaded(pending) { - if (pending.every(function(module) { + if (pending.every(function (module) { return module.def; })) { - pending.forEach(function(module) { + pending.forEach(function (module) { initializeModule(module.def); }); } @@ -185,7 +185,7 @@ var displaySystem = (function() { // add html if (def.template) { var d = document.createElement('div'); - d.className = 'moduleContainer '+def.name; + d.className = 'moduleContainer ' + def.name; d.innerHTML = def.template; document.getElementById('mainContainer').appendChild(d); } @@ -196,14 +196,14 @@ var displaySystem = (function() { prependToHead(s); } // register api - var m,cfg; + var m, cfg; if (def.factory) { if (def.name) { //TODO: this is a bit of a tight coupling between names in config and module names cfg = config.modules[def.name]; } - m = def.factory(cfg,function(action, handler) { - return onMessage(def,action,handler); + m = def.factory(cfg, function (action, handler) { + return onMessage(def, action, handler); }); } if (def.name) { diff --git a/modules/sprite.js b/modules/sprite.js index 4245b0a..a64138e 100644 --- a/modules/sprite.js +++ b/modules/sprite.js @@ -8,8 +8,12 @@ displaySystem.registerModule({ position: absolute; } `, - factory: function(config,onMessage) { + factory: function (config, onMessage) { var sprites = []; + var texts = []; + + + var hostAddress; function getElement() { return document.getElementById('sprite'); @@ -40,19 +44,48 @@ displaySystem.registerModule({ function addSprite(config) { let sprite = document.createElement('div'); sprite.className = 'sprite'; - sprite.innerHTML = config.html || ''; + var imgSrc = config.html || `http://${window.location.hostname}:1395/${config.alias}`||''; + var img = document.createElement('img'); + img.setAttribute("src", imgSrc); + img.setAttribute("class", config.imgClass); + sprite.appendChild(img); Object.keys(config).forEach((key) => { - sprite.style[key] = config[key]; + if (key === "id") { + sprite.id = config[key]; + } + else { + sprite.style[key] = config[key]; + } }); getElement().appendChild(sprite); return sprite; } + function addText(config) { + let text = document.createElement('span'); + text.setAttribute("class", "eventName"); + + text.innerHTML = config.data; + getElement().appendChild(text); + } + function addTextsToArray(config) { + texts.push.apply(texts, config); + } + function setText(configText) { + texts.forEach(removeSprite); + addTextsToArray(configText); + configText.forEach(addText); + } function set(configSprites) { sprites.forEach(removeSprite); sprites = configSprites.map(addSprite); } - + if (config.data) { + sprites = config.data; + } + if (config.texts) { + setText(config.texts); + } if (config.sprites) { set(config.sprites); } diff --git a/modules/table.js b/modules/table.js index ce07525..8bc91f0 100644 --- a/modules/table.js +++ b/modules/table.js @@ -27,7 +27,8 @@ displaySystem.registerModule({ //text-align: left; } */ - factory: function(config,onMessage) { + factory: function (config, onMessage) { + var numberOfLines = 8; var pageTimeout = 5000; var pageTimer; @@ -57,24 +58,24 @@ displaySystem.registerModule({ function setFromString(pasteFromExcel) { var lines = pasteFromExcel.trim().split(/[\n\r]+/); - var data = lines.map(function(line) { + var data = lines.map(function (line) { return line.split(/\t/); }); header = data.shift(); - set(data,header); + set(data, header); } - function setPage(data,header,page) { - var pageData = data.slice(page*numberOfLines,(page+1)*numberOfLines); + function setPage(data, header, page) { + var pageData = data.slice(page * numberOfLines, (page + 1) * numberOfLines); var head = ''; if (header) { - head = ''+header.join('')+''; + head = '' + header.join('') + ''; } - var html = pageData.slice(0,numberOfLines).map(function(row) { + var html = pageData.slice(0, numberOfLines).map(function (row) { return [ '', - row.map(function(cell,i,a) { + row.map(function (cell, i, a) { return [ '', cell, @@ -87,24 +88,24 @@ displaySystem.registerModule({ getElement().innerHTML = head + html; } - function nextPage(data,header,page) { + function nextPage(data, header, page) { var pages = Math.ceil(data.length / numberOfLines); var current = page; - var next = (current+1) % pages; - setPage(data,header,current); + var next = (current + 1) % pages; + setPage(data, header, current); if (pageTimer) { window.clearTimeout(pageTimer); pageTimer = null; } if (running) { - pageTimer = window.setTimeout(function() { - nextPage(data,header,next); - },pageTimeout); + pageTimer = window.setTimeout(function () { + nextPage(data, header, next); + }, pageTimeout); } } - function set(data,header) { - nextPage(data,header,0); + function set(data, header) { + nextPage(data, header, 0); } function start() { @@ -135,17 +136,17 @@ displaySystem.registerModule({ } if (config.data) { if (config.data instanceof Array) { - set(config.data,config.header); + set(config.data, config.header); } else { - setFromString(config.data,config.header); + setFromString(config.data, config.header); } } if (config.visible) { show(); } - onMessage('setData',function(msg) { - set(msg.data.data,msg.data.header); + onMessage('setData', function (msg) { + set(msg.data.data, msg.data.header); }); return { diff --git a/themes/fll/fll.css b/themes/fll/fll.css index e76e19b..5026a5a 100644 --- a/themes/fll/fll.css +++ b/themes/fll/fll.css @@ -3,7 +3,11 @@ body { visibility: visible; } + + + /* time definitions */ + #time { left: -20vw; transform: translate(20vw); @@ -17,6 +21,7 @@ body { padding-left: 3vh; padding-right: 1vh; } + #time::after { content: ''; width: 2.5vh; @@ -35,7 +40,9 @@ body { transform: translate(0); } + /* clock */ + #clock { right: -20vw; transform: translate(-20vw); @@ -72,14 +79,18 @@ body { #clock.stopped { background-color: crimson; } + #clock.stopped::before { border-color: crimson transparent; } + #clock.armed { color: crimson; } + /* list */ + #list { background-image: url(fll_list_bkg.png); background-size: 100% 100%; @@ -92,17 +103,22 @@ body { left: 12.5vw; padding: 4vw; } + #list.hidden { opacity: 0; } + #list .header { text-align: center; } + #list .cell { padding-left: 3vh; } + /* table defenitions */ + #table { color: #FFD204; background: black; @@ -112,7 +128,9 @@ body { border: #FFD204 1px solid; } + /* lowThird definitions */ + #lowThird { background-image: url(fll_lowThird_bkg.png); background-size: cover; @@ -123,16 +141,20 @@ body { padding-left: 22vw; transition: transform 0.3s; } -#lowThird.hidden { + +#lowThird.hidden { transform: translateY(120%); } + #lowThird .line { padding-left: 3vh; box-sizing: border-box; position: relative; } + /* used ceaser to create custom easing functions: http://matthewlein.com/ceaser/ */ + #lowThird .line1 { /*background-color: darkblue;*/ width: 80%; @@ -149,7 +171,9 @@ body { line-height: 8vh; } + /* ticker */ + #twitter { font-size: 6vh; padding: 0.2em; @@ -170,10 +194,11 @@ body { font-weight: bold; } -#twitter .message { -} +#twitter .message {} + /* gallery */ + #gallery div { transition: none; -} +} \ No newline at end of file diff --git a/themes/fll/flltable.css b/themes/fll/flltable.css new file mode 100644 index 0000000..748401f --- /dev/null +++ b/themes/fll/flltable.css @@ -0,0 +1,487 @@ +/** + * darkblue = rgb(0,0,139) + * crimsonred = rgb(237,20,61) + */ + +body { + font-family: benchnineregular, verdana, helvetica, sans-serif; + visibility: visible; +} + +img.emojione { + height: 1em; +} + + +/* time definitions */ + +@media screen { + #time { + left: -11em; + top: 2vh; + transform: translate(10em); + font-family: benchninebold; + color: white; + transition: transform 0.3s; + height: 1.2em; + font-size: 8vh; + line-height: 1.2em; + padding-left: 1.25em; + padding-right: 0.5em; + padding-top: 0.05em; + text-align: right; + box-sizing: border-box; + color: black; + text-shadow: 0.05em 0.05em 0.1em rgba(0, 0, 0, 0.5); + } + #time::before { + content: ''; + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + background: linear-gradient(to right, rgba(0, 0, 139, 0.9) 0%, rgba(0, 0, 139, 0.7) 100%); + background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(214, 214, 214, 0.8) 100%); + box-sizing: border-box; + border: 0.05em solid rgba(255, 255, 255, 0.5); + transform: skew(-20deg); + border-radius: 0.5em / 1em; + transition: all 1s; + z-index: -1; + } + #time.hidden { + transform: translate(0); + } +} + + +/* clock */ + +@media screen { + #clock { + right: -11em; + top: 2vh; + transform: translate(-10em); + font-family: benchninebold; + color: white; + transition: transform 0.3s; + height: 1.2em; + font-size: 8vh; + line-height: 1.2em; + padding-left: 0.5em; + padding-top: 0.05em; + box-sizing: border-box; + text-align: left; + width: 3.5em; + box-sizing: border-box; + color: black; + text-shadow: 0.05em 0.05em 0.1em rgba(0, 0, 0, 0.5); + } + #clock::before { + content: ''; + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(214, 214, 214, 0.8) 100%); + box-sizing: border-box; + border: 0.05em solid rgba(255, 255, 255, 0.5); + transform: skew(-20deg); + border-radius: 0.5em / 1em; + transition: all 1s; + z-index: -1; + } + #clock.hidden { + transform: translate(0); + } + #clock.stopped::before { + background: linear-gradient(to bottom, rgba(237, 20, 61, 1) 0%, rgba(237, 20, 61, 0.8) 100%); + } + #clock.armed { + color: crimson; + } +} + + +/* table definitions */ + +@media screen { + #table { + color: white; + background: linear-gradient(to right, rgba(0, 0, 139, 0.9) 0%, rgba(0, 0, 139, 0.7) 100%); + border: 0.05em solid rgba(255, 255, 255, 0.5); + border-radius: 0.5em / 1em; + text-shadow: 0.05em 0.05em 0.1em rgba(0, 0, 0, 1); + text-transform: uppercase; + line-height: 1.2em; + border-spacing: 0; + margin: 19vh auto; + overflow: hidden; + font-size: 4vh; + opacity: 0; + transition: all 1s; + } + #table thead tr { + background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(214, 214, 214, 0.8) 100%); + color: black; + text-shadow: 0.05em 0.05em 0.1em rgba(0, 0, 0, 0.5); + } + #table th { + font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; + } + #table th, #table td { + border-bottom: 1px solid rgba(255, 255, 255, 0.5); + } + #table.hidden { + opacity: 0; + } + #table.visible { + opacity: 1; + } + tr { + padding-left: 1em; + padding-right: 1em; + } + table#table td:first-child { + width: 4%; + } + table#table td:nth-child(2) { + width: 7%; + } + table#table td:nth-child(3) { + text-align: left; + } + table#table td:nth-child(4) { + width: 3.5em; + font-size: 4.5vh; + font-weight: bold; + color: #1cce1e; + } + table#table td:nth-child(5) { + width: 2.8em; + } + table#table td:nth-child(6) { + width: 2.8em; + } + table#table td:nth-child(7) { + width: 2.8em; + } + table td { + border-left: 1px solid #000; + border-right: 1px solid #000; + } +} + +/* Top Left */ +#challenge { + width: 100%; + top: 0.5vh; + left: 2vh; + font-size: 8vh; + text-align: left; + color: rgba(255, 255, 255, 0.5); +} +/* Top Center */ +.eventName { + position: absolute; + top: 3%; + /* width: 100%; */ + text-align: center; + border: #1e68d8; + border-radius: 20px; + background: linear-gradient(#e6e6ee,#b6b6db,#e6e6ee); + border-width: 3px; + border-style: solid; + font-size: 6vh; + color:#3131a7; + margin-left: 32%; + padding: 15px 20px; + font-weight: bold; + font-family: sans-serif; +} +/* Top Right */ +#FIRST { + width: 100%; + top: 3vh; + right: 3vh; + font-size: 8vh; + text-align: right; + color: rgba(255, 255, 255, 0.5); +} +/* Bottom Left*/ +#sponsor1 { + width: 100%; + bottom: 0.5vh; + font-size: 8vh; + text-align: left; + color: rgba(255, 255, 255, 0.5); +} + +/* Bottom Center */ + +#LEGOEd { + width: 100%; + bottom: 0.5vh; + font-size: 8vh; + /* right: 0.5vh; */ + text-align: center; + color: rgba(255, 255, 255, 0.5); +} +/* Bottom Left */ +#sponsor2 { + width: 100%; + bottom: 0.5vh; + font-size: 8vh; + text-align: right; + color: rgba(255, 255, 255, 0.5); +} + +.firstLogo { + height: 1.4em; + margin-left: 5vh; +} + +.challengeLogo { + height: 2.1em; +} + +.legoLogo { + height: 1.3em; + margin-right: 5vh; +} + +.sponsor1Img { + height: 1em; + margin-left: 5vh; +} + +.sponsor2Img { + height: 1.4em; + margin-right: 5vh; +} + +#top { + align-items: center; + display: flex; + top: 0vh; + width: 100%; +} + +#bottom { + align-items: center; + display: flex; + bottom: 0vh; + width: 100%; +} + + + + +/* list */ + +@media screen { + #list { + color: white; + text-shadow: 0.05em 0.05em 0.1em rgba(0, 0, 0, 1); + text-transform: uppercase; + line-height: 1.2em; + font-size: 5vh; + margin: 15vh auto; + } + #list .list-row { + background-color: rgba(0, 0, 139, 1); + background: linear-gradient(to right, rgba(0, 0, 139, 0.9) 0%, rgba(0, 0, 139, 0.7) 100%); + border: 0.05em solid rgba(255, 255, 255, 0.5); + transform: skew(-20deg); + border-radius: 0.5em / 1em; + transition: all 1s; + } + #list .list-cell { + text-align: left; + transform: scale(1); + transition: all 1s; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.15em; + /* benchnine uppercase is slighly off center */ + white-space: nowrap; + } + #list .list-cell.number { + text-align: right; + } + #list .list-head.list-row { + background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(214, 214, 214, 0.8) 100%); + opacity: 1; + } + #list .list-head.list-cell { + color: black; + text-shadow: 0.05em 0.05em 0.1em rgba(0, 0, 0, 0.5); + font-size: 6vh; + line-height: 1.2em; + text-align: center; + } + #list.hidden .list-row.list-row-even { + transform: translateX(-120vw) scaleY(0.1); + } + #list.hidden .list-cell.list-row-even { + opacity: 0; + transform: translateX(-120vw) scaleY(0.1); + } + #list.hidden .list-row.list-row-odd { + transform: translateX(120vw) scaleY(0.1); + } + #list.hidden .list-cell.list-row-odd { + opacity: 0; + transform: translateX(120vw) scaleY(0.1); + } + /* alternative animation + #list.hidden .list-row.list-row-even { + opacity: 0; + transform: scaleY(0.1); + } + #list.hidden .list-cell.list-row-even { + opacity: 0; + transform: scaleY(0.1); + } + #list.hidden .list-row.list-row-odd { + opacity: 0; + transform: scaleY(0.1); + } + #list.hidden .list-cell.list-row-odd { + opacity: 0; + transform: scaleY(0.1); + } + */ +} + +@keyframes swirl { + from { + transform: scale(3, 1) translate(5vh, 10vh) rotate(30deg); + } + 20% { + transform: scale(1, 2) translate(-20vh, -8vh) rotate(-3deg); + } + 60% { + transform: scale(2, 2) translate(10vh, 0vh) rotate(-10deg); + } + to { + transform: scale(3, 1) translate(5vh, 10vh) rotate(30deg); + } +} + + +/* lowThird definitions */ + +@media screen { + #lowThird { + background: none; + height: 22vh; + box-sizing: border-box; + } + #lowThird .line { + left: -4vh; + color: white; + transition: transform 0.3s; + transform: translate(0); + box-sizing: border-box; + position: relative; + padding-left: 8vh; + padding-top: 0.05em; + overflow: hidden; + } + #lowThird.hidden .line { + transform: translate(-120%); + } + /* used ceaser to create custom easing functions: http://matthewlein.com/ceaser/ */ + #lowThird .line1 { + width: 80%; + transition-timing-function: cubic-bezier(0.250, 0.100, 0.000, 1.000); + font-size: 8vh; + height: 10vh; + line-height: 10vh; + z-index: 2; + } + #lowThird .line1::before { + content: ''; + width: 99%; + height: 100%; + box-sizing: border-box; + position: absolute; + left: 0; + top: 0; + background: linear-gradient(to right, rgba(0, 0, 139, 0.9) 0%, rgba(0, 0, 139, 0.7) 100%); + border: 0.05em solid rgba(255, 255, 255, 0.5); + transform: skew(-20deg); + border-radius: 0.5em / 1em; + transition: all 1s; + z-index: -1; + } + #lowThird .line1::after { + content: ''; + position: absolute; + width: 20vh; + height: 40vh; + border-radius: 50%; + border: 2px solid rgba(255, 255, 255, 0.2); + border-width: 1vh 0.5vh; + top: 50%; + margin-top: -20vh; + left: 50%; + margin-left: -10vh; + animation: 40s linear infinite normal swirl; + } + #lowThird .line2 { + width: 70%; + transition-timing-function: cubic-bezier(1.000, 0.000, 0.695, 1.000); + font-size: 5vh; + height: 8vh; + line-height: 8vh; + } + #lowThird .line2::before { + content: ''; + width: 99%; + height: 100%; + box-sizing: border-box; + position: absolute; + left: 0; + top: 0; + background: linear-gradient(to right, rgba(237, 20, 61, 0.9) 0%, rgba(237, 20, 61, 0.7) 100%); + border: 0.05em solid rgba(255, 255, 255, 0.5); + transform: skew(-20deg); + border-radius: 0.5em / 1em; + transition: all 1s; + z-index: -1; + } +} + + +/* ticker */ + +@media screen {} + +@media screen { + #twitter { + font-size: 6vh; + height: 1.2em; + padding: 0.2em; + background: linear-gradient(to right, rgba(0, 0, 139, 0.9) 0%, rgba(0, 0, 139, 0.7) 100%); + border-top: 0.05em solid rgba(255, 255, 255, 0.5); + color: white; + transition: bottom 0.3s, visibility 0.3s; + } + #twitter.hidden { + bottom: -4em; + } + #twitter .tweet { + font-size: 6vh; + line-height: 1.2em; + height: 1.2em; + padding-top: 0.05em; + } + #twitter .author { + font-weight: bold; + } + #twitter .message {} +} \ No newline at end of file