diff --git a/config.js b/config.js index bd2edeb..8f6d720 100644 --- a/config.js +++ b/config.js @@ -14,11 +14,11 @@ displaySystem.config({ // color: "lime", }, 'camera': { - visible: true, + // visible: true, // audio: true, }, 'gallery': { - // visible: true, + visible: true, transition: 'fade', size: 'cover', timeout: 4, @@ -27,14 +27,17 @@ displaySystem.config({ 'http://lorempixel.com/640/480/people/2', 'http://lorempixel.com/640/480/people/3', 'http://lorempixel.com/640/480/people/4' - ] + ], + pages: [ + // 'http://www.fll-tools.com/' + ], }, 'clock': { - // visible: true, + visible: true, // countdown: 20, }, 'time': { - // visible: true, + visible: true, // format: "MM:ss", }, 'twitter': { @@ -43,28 +46,39 @@ displaySystem.config({ }, 'lowThird': { visible: true, - line1: 'press \'C\'', + line1: '❀️ press \'C\'', line2: 'to show the control window', }, 'list': { // visible: true, header: 'results round 1', data: [ - ['just try',1], - ['to copy',2], - ['and paste',3], - ['some cells',4], - ['from excel',5], - ['into the control',6], - ['window! You\'ll be',7], - ['amazed!',8], - ['It even has',8], - ['automatic',8], - ['paging',8], + ['πŸ‡³πŸ‡± just try',1], + ['πŸ‡³πŸ‡± to copy',2], + ['πŸ‡ͺπŸ‡¬ and paste',3], + ['πŸ‡ͺπŸ‡¬ some cells',4], + ['πŸ‡ͺπŸ‡¬ from excel',5], + ['πŸ‡ΊπŸ‡Έ into the control',6], + ['πŸ‡ΊπŸ‡Έ window! You\'ll be',7], + ['πŸ‡ΊπŸ‡Έ amazed!',8], + ['πŸ‡³πŸ‡± It even has',8], + ['πŸ‡³πŸ‡± automatic',8], + ['πŸ‡³πŸ‡± paging',8], ], timer: 5000, lines: 8 }, + 'sprite': { + // visible: true, + sprites: [{ + width: '100%', + top: '3.5vh', + fontSize: '8vh', + textAlign: 'center', + color: 'rgba(255,255,255,0.5)', + html: 'FIRST LEGO League' + }] + }, 'table': { // visible: true, header: ['team name', 'number', 'score 1', 'score 2'], @@ -85,10 +99,24 @@ displaySystem.config({ lines: 8 }, 'css': { - href: 'themes/rednblue.css', - // href: 'themes/default.css', + href: [ + 'themes/rednblue-plus/rednblue-plus.css', + // 'themes/rednblue-plus/rednblue-plus-mod-rtl.css', + // 'themes/rednblue-plus/rednblue-plus-mod-opaque.css' + ], + // href: [ + // 'themes/rednblue/rednblue.css', + // // 'themes/rednblue/rednblue-mod-rtl.css' + // ], + // href: 'themes/default/default.css', // gist: '9c7e4efaba9dbbc4831b' }, + 'geometry': { + zoom: 1, + aspect: 'native', + rotation: 0, + overscan: [0,0,0,0] + }, 'keybindings': { 'q': 'time.show()', 'a': 'time.hide()', @@ -100,6 +128,8 @@ displaySystem.config({ 'f': 'twitter.hide()', 't': 'list.show()', 'g': 'list.hide()', + 'y': 'table.show()', + 'h': 'table.hide()', 'c': 'controls.open()', // 'c': function() { // window.open('controls.html','fllDisplayControlWindow','resize=yes,width=800,height=350'); @@ -107,8 +137,12 @@ displaySystem.config({ }, 'controls': { //url: + }, + 'emojione': { + // displays emoji characters + selector: '.line1, .list-cell, .tweet' } }, //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 b15e397..5f45a55 100644 --- a/css/style.css +++ b/css/style.css @@ -4,8 +4,19 @@ html, body { margin: 0; padding: 0; } -/* hides screen during initialization */ -.curtain { + + + +/* 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; } @@ -17,12 +28,15 @@ html, body { bottom: 0; } + /* control window */ + @media screen { body.controls { font-family: verdana, helvetica, sans-serif; font-size: 12px; padding: 12px; + visibility: visible; } body.controls .instructions { text-align: right; @@ -35,8 +49,7 @@ html, 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; diff --git a/index.html b/index.html index f833c14..c673f6b 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,15 @@ + Overlay +
- \ No newline at end of file + diff --git a/js/main.js b/js/main.js index 67b1f99..8a18648 100644 --- a/js/main.js +++ b/js/main.js @@ -1,26 +1,5 @@ -//adapted from https://github.com/sindresorhus/multiline -var multiline = (function() { - // start matching after: comment start block => ! or @preserve => optional whitespace => newline - // stop matching before: last newline => optional whitespace => comment end block - var reCommentContents = /\/\*!?(?:\@preserve)?[ \t]*(?:\r\n|\n)([\s\S]*?)(?:\r\n|\n)[ \t]*\*\//; - - return function (fn) { - if (typeof fn !== 'function') { - throw new TypeError('Expected a function'); - } - - var match = reCommentContents.exec(fn.toString()); - - if (!match) { - throw new TypeError('Multiline comment missing.'); - } - - return match[1]; - }; -}()); - // display system main -var displaySystem = (function() { +var displaySystem = (function () { var system = {}; var config; var modules = {}; @@ -30,20 +9,31 @@ var displaySystem = (function() { function setConfig(_config) { config = _config; - closeCurtain(); - 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) { + var h = document.getElementsByTagName('head')[0]; + h.appendChild(el); } - function loadScript(src,onload) { + function loadScript(src, onload) { var el = document.createElement('script'); el.src = src; el.onload = onload; - prependToHead(el); + appendToHead(el); + } + + function loadCss(src, onLoad) { + var el = document.createElement('link'); + el.rel = 'stylesheet'; + el.href = src; + appendToHead(el); } var connected = false; @@ -58,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", @@ -74,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); @@ -100,14 +90,16 @@ var displaySystem = (function() { function connect() { ws = initWebsocket(config); - system.ws = { - sendMessage: sendMessage - }; + if (ws) { + system.ws = { + sendMessage: sendMessage + }; + } } 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 = {}; @@ -121,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] = []; } @@ -161,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); }); @@ -176,13 +168,12 @@ 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); }); - openCurtain(); } } @@ -190,21 +181,13 @@ var displaySystem = (function() { lastModule = def; } - function closeCurtain(){ - document.body.classList.add('curtain'); - } - - function openCurtain(){ - document.body.classList.remove('curtain'); - } - function initializeModule(def) { // add html if (def.template) { var d = document.createElement('div'); - d.className = 'moduleContainer'; + d.className = 'moduleContainer ' + def.name; d.innerHTML = def.template; - document.body.appendChild(d); + document.getElementById('mainContainer').appendChild(d); } // add styles if (def.style) { @@ -213,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) { @@ -235,10 +218,12 @@ var displaySystem = (function() { system = { config: setConfig, - registerModule: registerModule, - modules: modules, - definitions: moduleDefs + registerModule, + modules, + definitions: moduleDefs, + loadScript, + loadCss }; return system; -}()); \ No newline at end of file +}()); diff --git a/modules/background.js b/modules/background.js index 63f92a0..5dbad79 100644 --- a/modules/background.js +++ b/modules/background.js @@ -1,7 +1,7 @@ displaySystem.registerModule({ name: 'background', template: '
', - style: multiline(function() {/* + style: ` #background { position: absolute; left: 0; @@ -12,7 +12,7 @@ displaySystem.registerModule({ #background.hidden { display: none; } - */}), + `, factory: function(config) { var el; @@ -29,11 +29,13 @@ displaySystem.registerModule({ } function show() { - getElement().className = ''; + getElement().classList.remove('hidden'); + getElement().classList.add('visible'); } function hide() { - getElement().className = 'hidden'; + getElement().classList.add('hidden'); + getElement().classList.remove('visible'); } if (config.color) { @@ -50,4 +52,4 @@ displaySystem.registerModule({ clear: clear }; } -}); \ No newline at end of file +}); diff --git a/modules/camera.js b/modules/camera.js index 75bc71d..9c71bea 100644 --- a/modules/camera.js +++ b/modules/camera.js @@ -1,18 +1,19 @@ displaySystem.registerModule({ name: 'camera', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` #camera { position: absolute; left: 0; top: 0; width: 100%; height: 100%; + object-fit: cover; } #camera.hidden { @@ -38,7 +39,7 @@ displaySystem.registerModule({ } } - */}), + `, factory: function(config) { var el; var useAudio = false; @@ -101,11 +102,13 @@ displaySystem.registerModule({ } function show() { - getElement().className = ''; + getElement().classList.remove('hidden'); + getElement().classList.add('visible'); } function hide() { - getElement().className = 'hidden'; + getElement().classList.add('hidden'); + getElement().classList.remove('visible'); } if (config.audio) { @@ -122,4 +125,4 @@ displaySystem.registerModule({ hide: hide }; } -}); \ No newline at end of file +}); diff --git a/modules/clock.js b/modules/clock.js index 3293211..5b636a4 100644 --- a/modules/clock.js +++ b/modules/clock.js @@ -1,9 +1,9 @@ displaySystem.registerModule({ name: 'clock', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` @import url('fonts/lcd-bold.css'); #clock { @@ -13,7 +13,7 @@ displaySystem.registerModule({ color: white; font-size: 96px; } - */}), + `, factory: function(config) { var div; var bgColor = 'black'; @@ -131,10 +131,12 @@ displaySystem.registerModule({ function show() { getElement().classList.remove('hidden'); + getElement().classList.add('visible'); } function hide() { getElement().classList.add('hidden'); + getElement().classList.remove('visible'); } if (config.countdown) { @@ -154,4 +156,4 @@ displaySystem.registerModule({ pause: playPause }; } -}); \ No newline at end of file +}); diff --git a/modules/controls.js b/modules/controls.js index 3106564..fa5ec57 100644 --- a/modules/controls.js +++ b/modules/controls.js @@ -68,7 +68,7 @@ displaySystem.registerModule({ document.body.appendChild(p); } - var html = multiline(function() {/* + var html = ` @@ -82,13 +82,13 @@ displaySystem.registerModule({

- */}) + ` function open() { if (config.url) { - var win = window.open(config.url,'fllDisplayControlWindow','resize=yes,width=800,height=350'); + var win = window.open(config.url,'fllDisplayControlWindow','resize=yes,width=800,height=550'); } else { - var win = window.open('','fllDisplayControlWindow','resize=yes,width=800,height=350'); + var win = window.open('','fllDisplayControlWindow','resize=yes,width=800,height=550'); win.document.write(html); init(win.document); } @@ -99,4 +99,4 @@ displaySystem.registerModule({ open: open } } -}); \ No newline at end of file +}); diff --git a/modules/css.js b/modules/css.js index ec675ca..e8a582e 100644 --- a/modules/css.js +++ b/modules/css.js @@ -1,21 +1,29 @@ displaySystem.registerModule({ name: 'css', factory: function(config) { - var el, gistEl; + var els = [], gistEl; - function createElements() { + function appendSheet(href) { el = document.createElement('link'); el.rel = 'stylesheet'; + el.href = href; document.head.appendChild(el); + return el; + } + + function removeSheet(el) { + document.head.removeChild(el); + } + + function createElements() { gistEl = document.createElement('link'); gistEl.rel = 'stylesheet'; document.head.appendChild(gistEl); } function setCss(href) { - if (href) { - el.href = href; - } + els.forEach(removeSheet); + els = [].concat(href).map(appendSheet); } function setGist(id) { @@ -60,4 +68,4 @@ displaySystem.registerModule({ gist: setGist }; } -}); \ No newline at end of file +}); diff --git a/modules/emojione.js b/modules/emojione.js new file mode 100644 index 0000000..91dbea7 --- /dev/null +++ b/modules/emojione.js @@ -0,0 +1,41 @@ +displaySystem.registerModule({ + name: 'emojione', + factory: function(config) { + + function convertNode(node) { + node.innerHTML = emojione.toImage(node.innerHTML); + } + + function scan() { + var nodes = document.querySelectorAll(config.selector); + nodes.forEach(convertNode) + } + + displaySystem.loadCss('https://cdn.jsdelivr.net/emojione/3.0./extras/css/emojione.min.css'); + displaySystem.loadScript('https://cdn.jsdelivr.net/emojione/3.0.3/lib/js/emojione.min.js', () => { + let observer = new MutationObserver((records) => { + // console.log(records); + records.forEach(record => { + record.addedNodes.forEach(node => { + if (node.matches && node.matches(config.selector)) { + convertNode(node); + console.log(node); + } + }) + }) + }); + observer.observe(document.body, { + childList: true, + characterData: true, + subtree: true + }); + + scan(); + }); + + + return { + scan + } + } +}); diff --git a/modules/gallery.js b/modules/gallery.js index bdb81cc..2d3539a 100644 --- a/modules/gallery.js +++ b/modules/gallery.js @@ -1,11 +1,10 @@ displaySystem.registerModule({ name: 'gallery', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` #gallery { position: absolute; left: 0; @@ -24,7 +23,7 @@ displaySystem.registerModule({ width: 100%; height: 100%; left: 0; - right: 0; + top: 0; background-size: contain; background-repeat: no-repeat; background-position: center center; @@ -33,38 +32,71 @@ displaySystem.registerModule({ #gallery div.current { opacity: 1; } - */}), + #gallery iframe { + opacity: 0; + position: absolute; + width: 100%; + height: 100%; + left 0; + top: 0; + border: none; + transition: all 1s; + } + #gallery iframe.current { + opacity: 1; + } + `, factory: function(config) { - var el, imageElements = [], currentIndex, timer; + var el, containerElements = [], currentIndex = 0, timer; function getElement() { return el?el:(el=document.getElementById('gallery')); } + function clear() { + var container = getElement(); + container.innerHTML = ''; + containerElements = []; + } + function load(images) { if (typeof images === 'string') { - load(images.split(/(\r\n|\r|\n/gi)); + return load(images.split(/(\r\n|\r|\n)/gi)); } var container = getElement(); - container.innerHTML = ''; - imageElements = images.map(function(img) { + containerElements = containerElements.concat(images.map(function(img) { var newEl = container.appendChild(document.createElement('div')); newEl.style.backgroundImage = 'url('+img+')'; newEl.style.backgroundSize = config.size||'cover'; return newEl; - }); + })); + set(0); + } + + function loadPages(pages) { + if (typeof pages === 'string') { + return loadPages(pages.split(/(\r\n|\r|\n)/gi)); + } + var container = getElement(); + containerElements = containerElements.concat(pages.map(function(page) { + var newEl = container.appendChild(document.createElement('iframe')); + newEl.src = page; + return newEl; + })); set(0); } function show() { - getElement().className = ''; + getElement().classList.remove('hidden'); + getElement().classList.add('visible'); if (config.timeout && !timer) { timer = window.setInterval(next,config.timeout * 1000); } } function hide() { - getElement().className = 'hidden'; + getElement().classList.add('hidden'); + getElement().classList.remove('visible'); if (timer) { window.clearInterval(timer); timer = null; @@ -72,21 +104,29 @@ displaySystem.registerModule({ } function set(index) { - imageElements[currentIndex||0].classList.remove('current'); - imageElements[currentIndex = index].classList.add('current'); + if (containerElements[currentIndex]) { + containerElements[currentIndex].classList.remove('current'); + } + currentIndex = index; + if (containerElements[currentIndex]) { + containerElements[currentIndex].classList.add('current'); + } } function next() { - set((currentIndex+1)%imageElements.length); + set((currentIndex+1)%containerElements.length); } function prev() { - set((currentIndex+imageElements.length-1)%imageElements.length); + set((currentIndex+containerElements.length-1)%containerElements.length); } if (config.images) { load(config.images); } + if (config.pages) { + loadPages(config.pages); + } if (config.visible) { show(); } @@ -97,7 +137,8 @@ displaySystem.registerModule({ prev: prev, next: next, set: set, - load: load + load: function(images) { clear(); load(images); }, + pages: function(pages) { clear(); loadPages(pages); } }; } -}); \ No newline at end of file +}); diff --git a/modules/geometry.js b/modules/geometry.js new file mode 100644 index 0000000..2673565 --- /dev/null +++ b/modules/geometry.js @@ -0,0 +1,104 @@ +displaySystem.registerModule({ + name: 'geometry', + style: ` + #mainContainer { + position: absolute; + left: 50vw; + top: 50vh; + + } + `, + factory: function(config) { + var el; + + function getContainer() { + return el?el:(el=document.getElementById('mainContainer')); + } + + function getScale() { + return config.zoom||1; + }; + function getViewport() { + var overscan = config.overscan || [0,0,0,0]; + var w = document.body.clientWidth-overscan[1]-overscan[3]; + var h = document.body.clientHeight-overscan[0]-overscan[2]; + return { + w: w, + h: h, + a: w/h + }; + }; + function getAspect() { + if (typeof config.aspect==='number') { + return config.aspect; + } else { + return getViewport().a; + } + }; + + function redraw() { + var vp = getViewport(); + var scale = getScale(); + var scaleX = vp.a*scale/getAspect(); + var scaleY = scale; + //pixel size of the viewport (scaled) + var bw = vp.w/scaleX; + var bh = vp.h/scaleY; + //size of the rotated viewport + var width = ((config.rotation%180)===90)?bh:bw; + var height = ((config.rotation%180)===90)?bw:bh; + + var style = ''; + var rotate = 'rotate('+(config.rotation||0)+'deg)'; + var scaleX = 'scaleX('+scaleX+')'; + var scaleY = 'scaleY('+scaleY+')'; + var transform = scaleX+' '+scaleY+' '+rotate+';'; + style += '-webkit-transform: '+transform; + style += '-moz-transform: '+transform; + style += 'transform: '+transform; + style += 'width:'+width+'px;'; + style += 'height:'+height+'px;'; + //center + style += 'margin-left:'+(-width/2)+'px;'; + style += 'margin-top:'+(-height/2)+'px;'; + getContainer().style = style + } + + function right() { + config.rotation = (config.rotation + 90) % 360; + redraw(); + } + function left() { + config.rotation = (config.rotation + 270) % 360; + redraw(); + } + + function zoomin() { + config.zoom += 0.1; + redraw(); + } + + function zoomout() { + config.zoom -= 0.1; + redraw(); + } + + function zoomreset() { + config.zoom = 1; + redraw(); + } + + redraw(); + + window.addEventListener('resize', redraw); + + return { + left, + right, + zoomin, + zoomout, + zoomreset + + }; + } +}); diff --git a/modules/list.js b/modules/list.js index 6f6275b..4a10c38 100644 --- a/modules/list.js +++ b/modules/list.js @@ -1,22 +1,17 @@ displaySystem.registerModule({ name: 'list', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` #list { - position: absolute; - left: 25vw; - top: 10vh; - width: 50vw; - font-size: 6vh; - box-sizing: border-box; - } - #list .cell { - display: inline-block; - box-sizing: border-box; - } - */}), + width: calc(100% - 1em); + color: white; + display: grid; + grid-auto-columns: auto; + grid-auto-rows: auto; + } + `, factory: function(config,onMessage) { var numberOfLines = 8; var pageTimeout = 5000; @@ -34,12 +29,16 @@ displaySystem.registerModule({ timer = null; } } + function show() { getElement().classList.remove('hidden'); + getElement().classList.add('visible'); start(); } + function hide() { getElement().classList.add('hidden'); + getElement().classList.remove('visible'); stop(); } @@ -53,9 +52,14 @@ displaySystem.registerModule({ function setPage(data,header,page) { var pageData = data.slice(page*numberOfLines,(page+1)*numberOfLines); + var colTypes = (pageData[0]||[]).map(cell => { + return typeof cell; + }); var head = ''; if (header) { - head = '
'+header+'
'; + head = `
`; + let style = `grid-column: 1 / span ${colTypes.length}; grid-row: 1;`; + head += `
${header}
`; } //crude estimation of width fractions by string length @@ -67,21 +71,16 @@ displaySystem.registerModule({ },[]); var totalWidth = widths.reduce(function(all,w) {return all+w;},0); - var html = pageData.slice(0,numberOfLines).map(function(row) { + var html = pageData.slice(0,numberOfLines).map((cells, row) => { + let rowClass = (row%2)?'list-row-odd':'list-row-even'; + let r = header? row+2: row+1; return [ - '
', - row.map(function(cell,i,a) { - return [ - '
', - '', - cell, - '', - '
' - ].join(''); + `
`, + cells.map((cell,column) => { + let style = `grid-column: ${column + 1}; grid-row: ${r + 1};`; + let cellClass = colTypes[column]; + return `
${cell}
`; }).join(''), - '
' ].join(''); }).join(''); getElement().innerHTML = head + html; @@ -156,4 +155,4 @@ displaySystem.registerModule({ lines: setLines }; } -}); \ No newline at end of file +}); diff --git a/modules/lowThird.js b/modules/lowThird.js index 7f8a403..84b758d 100644 --- a/modules/lowThird.js +++ b/modules/lowThird.js @@ -1,9 +1,9 @@ displaySystem.registerModule({ name: 'lowThird', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` #lowThird { position: absolute; left: 0; @@ -11,7 +11,7 @@ displaySystem.registerModule({ bottom: 0; font-size: 10vh; } - */}), + `, factory: function(config, onMessage) { var visible = false; var timer; @@ -22,20 +22,23 @@ displaySystem.registerModule({ return document.getElementById('lowThird'); } function persist() { - getElement().className = ''; + getElement().classList.remove('hidden'); + getElement().classList.add('visible'); visible = true; if (timer) { clearTimeout(timer); timer = null; } } + function show() { persist(); timer = setTimeout(hide,5000); } function hide() { visible = false; - getElement().className = 'hidden'; + getElement().classList.add('hidden'); + getElement().classList.remove('visible'); } function setText(line1,line2) { line1text = line1||line1text; diff --git a/modules/sprite.js b/modules/sprite.js new file mode 100644 index 0000000..a64138e --- /dev/null +++ b/modules/sprite.js @@ -0,0 +1,103 @@ +displaySystem.registerModule({ + name: 'sprite', + template: ` + + `, + style: ` + #sprite .sprite { + position: absolute; + } + `, + factory: function (config, onMessage) { + var sprites = []; + var texts = []; + + + var hostAddress; + + function getElement() { + return document.getElementById('sprite'); + } + + function show() { + getElement().classList.remove('hidden'); + getElement().classList.add('visible'); + } + + function hide() { + getElement().classList.add('hidden'); + getElement().classList.remove('visible'); + } + + function showSprite(index) { + sprites[index].classList.remove('hidden'); + } + + function hideSprite(index) { + sprites[index].classList.add('hidden'); + } + + function removeSprite(el) { + el.parentNode.removeChild(el); + } + + function addSprite(config) { + let sprite = document.createElement('div'); + sprite.className = 'sprite'; + 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) => { + 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); + } + if (config.visible) { + show(); + } + + return { + show, + hide, + showSprite, + hideSprite, + }; + } +}); diff --git a/modules/table.js b/modules/table.js index d349154..8bc91f0 100644 --- a/modules/table.js +++ b/modules/table.js @@ -1,20 +1,14 @@ displaySystem.registerModule({ name: 'table', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` #table { - border-collapse: collapse; - margin: 20vh auto; width: calc(100% - 1em); - font-size: 5vh; color: white; background: black; } - #table.hidden { - display: none; - } #table td { text-align: center; white-space: nowrap; @@ -23,7 +17,7 @@ displaySystem.registerModule({ max-width: 0; width: 0; } - */}), + `, /* Add this to the style to cause the second column on each row to take the most space. Replace the number 2 in the selector for a similar effect on a different column @@ -33,7 +27,8 @@ displaySystem.registerModule({ //text-align: left; } */ - factory: function(config,onMessage) { + factory: function (config, onMessage) { + var numberOfLines = 8; var pageTimeout = 5000; var pageTimer; @@ -52,33 +47,35 @@ displaySystem.registerModule({ } function show() { getElement().classList.remove('hidden'); + getElement().classList.add('visible'); start(); } function hide() { getElement().classList.add('hidden'); + getElement().classList.remove('visible'); stop(); } 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, @@ -91,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() { @@ -139,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 { @@ -160,4 +157,4 @@ displaySystem.registerModule({ lines: setLines }; } -}); \ No newline at end of file +}); diff --git a/modules/time.js b/modules/time.js index 6da16b6..5c6fdf6 100644 --- a/modules/time.js +++ b/modules/time.js @@ -1,9 +1,9 @@ displaySystem.registerModule({ name: 'time', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` @import url('fonts/lcd-bold.css'); #time { @@ -13,7 +13,7 @@ displaySystem.registerModule({ color: white; font-size: 96px; } - */}), + `, factory: function(config) { var offset = 0; @@ -41,11 +41,13 @@ displaySystem.registerModule({ } function show() { - getElement().className = ''; + getElement().classList.remove('hidden'); + getElement().classList.add('visible'); } function hide() { - getElement().className = 'hidden'; + getElement().classList.add('hidden'); + getElement().classList.remove('visible'); } if (config.format) { @@ -185,4 +187,4 @@ dateFormat.i18n = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] -}; \ No newline at end of file +}; diff --git a/modules/twitter.js b/modules/twitter.js index 325a1ff..657396a 100644 --- a/modules/twitter.js +++ b/modules/twitter.js @@ -1,9 +1,9 @@ displaySystem.registerModule({ name: 'twitter', - template: multiline(function() {/* + template: ` - */}), - style: multiline(function() {/* + `, + style: ` #twitter { position: absolute; bottom: 0; @@ -22,7 +22,7 @@ displaySystem.registerModule({ padding-right: 1.5em; font-size: 6vh; } - */}), + `, factory: function(config,onMessage) { var tweetsIndex = {}; @@ -39,20 +39,22 @@ displaySystem.registerModule({ var speed = 100; var seq = 0; - function getTwitterDiv() { + function getElement() { return div?div:(div=document.getElementById('twitter')); } function getContainer() { - return container?container:(container = getTwitterDiv().firstChild); + return container?container:(container = getElement().firstChild); } function show() { - getTwitterDiv().className = ''; + getElement().classList.remove('hidden'); + getElement().classList.add('visible'); } function hide() { - getTwitterDiv().className = 'hidden'; + getElement().classList.add('hidden'); + getElement().classList.remove('visible'); } //sorting @@ -217,4 +219,4 @@ displaySystem.registerModule({ remove: remStr }; } -}); \ No newline at end of file +}); diff --git a/readme.md b/readme.md index b1311f9..a31e266 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,17 @@ -Display Systems +Display System, a FirstLegoLeague Module ================ -![rednblue theme](themes/rednblue.png) +## FLL Modules + +![](https://github.com/FirstLegoLeague/Coordination/wiki/National-setup.png) + +Display System can be a block in a larger framework of cooperating modules. Read more about it [here](https://github.com/FirstLegoLeague/Coordination/wiki) + +However, it can also be used standalone. + +## Display System + +![rednblue-plus theme](themes/rednblue-plus/rednblue-plus.png) This is a general purpose, configurable system for data display. It currently contains 8 modules, which are explained further on. @@ -30,12 +40,15 @@ Contents - [background](#background) - [camera](#camera) - [gallery](#gallery) + - [sprite](#sprite) - [clock](#clock) - [time](#time) - [list](#list) + - [table](#table) - [lowThird](#lowthird) - [twitter](#twitter) - [css](#css) + - [geometry](#geometry) - [keybindings](#keybindings) - [Theming](#theming) - [Included themes](#included-themes) @@ -196,9 +209,9 @@ Start: Send a message: //*nix - mhub-client -n twitter -t twitter:addMessage -d '{"id":123,"user":{"screen_name":"FLL"},"text":"FLL is great"}' + mhub-client -n default -t twitter:addMessage -d '{"id":123,"user":{"screen_name":"FLL"},"text":"FLL is great"}' //windows - mhub-client -n twitter -t twitter:addMessage -d "{""id"":123,""user"":{""screen_name"":""FLL""},""text"":""FLL is great""}" + mhub-client -n default -t twitter:addMessage -d "{""id"":123,""user"":{""screen_name"":""FLL""},""text"":""FLL is great""}" In your `config.js`, make sure you have the following options: @@ -258,7 +271,7 @@ Now test your twitter stream in the console: This would start streaming live twitter messages in your console. You are now one step away from connecting everything: - tweet stream lego --json | mhub-client -n twitter -t twitter:addMessage -i json + tweet stream lego --json | mhub-client -n default -t twitter:addMessage -i json This command uses [pipes](http://en.wikipedia.org/wiki/Pipeline_(Unix)) to take the output of the `tweet` utility and *pipe* it into `mhub-client`. @@ -282,14 +295,14 @@ Then make sure that in the mhub-server config (`server.conf.json`), the `time` n Then pipe it through to an mhub-client instance: - cli-time -m json -i | mhub-client -n time -t time:set -i json + cli-time -m json -i | mhub-client -n default -t time:set -i json To set the time to 0 and start counting: //*nix - mhub-client -n time -t time:set -d '{"timestamp":"0"}' + mhub-client -n default -t time:set -d '{"timestamp":"0"}' //windows - mhub-client -n time -t time:set -d "{""timestamp"":""0""}" + mhub-client -n default -t time:set -d "{""timestamp"":""0""}" Note that the `"0"` is quoted and it actually means setting the time to Jan 1 2000 at 00:00 in your local timezone. @@ -350,6 +363,11 @@ mhub topics: A gallery of images. Partially transparent images may be used to display for example some logos in corners of the screen. Note that in addition to displaying images, you can use a custom css stylesheet to completely customize your experience (this is somewhat of a more advanced usage though). +To store images online, use any image hosting service, like [imgur](http://imgur.com/), [postimage](https://postimage.io) or [tinypic](http://tinypic.com/) + + +Another option for gallery is to display arbitrary pages. These will be displayed in an `iframe`. Note that not all websites can be displayed this way. Some of them do not allow rendering in an iframe. + Configuration options: - `visible`: initial visibility, defaults to false, @@ -360,6 +378,8 @@ Configuration options: - `contain`: enlarge the image to fit the screen, there may be empty space around the image - `100% 100%`: stretch the image to fit the screen, it may become distorted - `auto`: display the image as is +- `images`: array of image urls +- `pages`: array of urls Exposed api: @@ -369,6 +389,7 @@ Exposed api: - `next()`: transition to next image - `set(index)`: sets the image specified by the index - `load(images)`: loads the given images, either as an array of strings or a single string of newline separated urls +- `pages(pages)`: loads the given pages, either as an array of strings or a single string of newline separated urls mhub topics: @@ -378,6 +399,34 @@ mhub topics: - `gallery:next` - `gallery:set` data: `{"index":}` - `gallery:load` data: `{"images":[]}` +- `gallery:pages` data: `{"pages":[]}` + +### sprite + +Simple individual images or bits of text that can be placed anywhere on the screen. This is useful for displaying watermarks or logos. + +To store images online, use any image hosting service, like [imgur](http://imgur.com/), [postimage](https://postimage.io) or [tinypic](http://tinypic.com/) + +Configuration options: + +- `visible`: initial visibility, defaults to false, +- `sprites`: an array of objects, containing + - `html` (optional): html content of the sprite. This can be text or more elaborate content + - ``: any css property to set. For example `left` or `top`. Note that the property names should be camelCased, like `marginLeft` + +Exposed api: + +- `show()`: show all sprites +- `hide()`: hide all sprites +- `showSprite(index)`: show a particular sprite +- `hideSprite(index)`: hide a particular sprite + +mhub topics: + +- `gallery:show` +- `gallery:hide` +- `gallery:showSprite` data: `{"index":}` +- `gallery:hideSprite` data: `{"index":}` ### clock @@ -546,7 +595,7 @@ To include custom styling, create a custom stylesheet to override a default styl Configuration options: -- `href`: url to a stylesheet, can be local, or hosted somewhere +- `href`: url to a stylesheet, can be local, or hosted somewhere. It can also be an array of stylesheets, which is used for theme modifiers. - `gist`: gist id to load alongside the stylesheet, can be used to customize themes Exposed api: @@ -555,6 +604,33 @@ Exposed api: - `gist`: load a stylesheet from a gist id. All css files are concatenated and used as data url - `reset`: resets the stylesheet back to the `config.js` option +### geometry + +This module controls screen geometry. It allows you to rotate the display, control overscan parameters and zoom. + +Configuration options: + +- `zoom`: zoom level of the window +- `aspect`: either the string "native" or the aspect ratio of the device used. This can be used to compensate for aspect ratio problems +- `rotation`: rotation of the display in degrees +- `overscan`: array of overscan amount in pixels + +Exposed api: + +- `right`: rotate right +- `left`: rotate left +- `zoomin`: zoom in with 10% +- `zoomout`: zoom out with 10% +- `zoomreset`: reset the zoom level to 1 + +mhub topics: + +- `geometry:right` +- `geometry:left` +- `geometry:zoomin` +- `geometry:zoomout` +- `geometry:zoomreset` + ### keybindings This is a module that handles key bindings. By default it can show and hide other modules and show the control window, as explained in the [Using key bindings](#using-key-bindings) section above. However, this module is completely user configurable. @@ -599,8 +675,8 @@ Themes can be used by pointing the `css` module configuration to a stylesheet. T ### Included themes -- `themes/default.css`: a colorful default theme that can be used to create your own -- `themes/rednblue.css`: a simple red and blue theme with slanted edges +- `themes/rednblue/rednblue.css`: a simple red and blue theme with slanted edges +- `themes/rednblue-plus/rednblue-plus.css`: an extra fancy red and blue theme For screenshots, see the `themes` [folder](themes) diff --git a/themes/default-rtl.css b/themes/default-rtl.css deleted file mode 100644 index 501bea5..0000000 --- a/themes/default-rtl.css +++ /dev/null @@ -1,102 +0,0 @@ -body { - font-family: verdana, helvetica, sans-serif; - direction: rtl; -} - -/* time definitions */ -#time { - font-size: 96px; - font-family: lcdbold; - color: white; - -webkit-text-fill-color: white; - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: black; - transition: top 0.3s; -} - -#time.hidden { - top: -2em; -} - -/* clock definitions */ -#clock { - font-size: 96px; - font-family: lcdbold; - color: #ffd204; - -webkit-text-fill-color: #ffd204; - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: black; - transition: top 0.3s; -} - -#clock.hidden { - top: -2em; -} -#clock.stopped { - color: red; - -webkit-text-fill-color: #c41425; -} -#clock.armed { - color: blue; - -webkit-text-fill-color: #0066b3; -} - -/* list */ -#list { - background-color: #ffd204; - opacity: 1; - transition: opacity 0.3s; -} -#list.hidden { - opacity: 0; -} -#list .header { - text-align: center; -} -#list .cell { - padding-right: 3vh; -} - -/* lowThird definitions */ -#lowThird { - background-color: #ffd204; - background-size: cover; - position: absolute; - height: 30vh; - padding: 2vh 5vw; - color: #6f2c91; - box-sizing: border-box; - transition: bottom 0.3s; -} - -#lowThird.hidden { - bottom: -30vh; -} - -#lowThird .line1 { - font-weight: bold; -} - -/* ticker */ -#twitter { - font-size: 6vh; - padding: 1em; - background-color: #0066b3; - color: white; - transition: bottom 0.3s; -} - -#twitter.hidden { - bottom: -4em; -} - -#twitter .tweet { - font-size: 6vh; -} - -#twitter .author { - font-weight: bold; -} - -#twitter .message { -} \ No newline at end of file diff --git a/themes/default.css b/themes/default.css deleted file mode 100644 index 5c483cc..0000000 --- a/themes/default.css +++ /dev/null @@ -1,101 +0,0 @@ -body { - font-family: verdana, helvetica, sans-serif; -} - -/* time definitions */ -#time { - font-size: 96px; - font-family: lcdbold; - color: white; - -webkit-text-fill-color: white; - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: black; - transition: top 0.3s; -} - -#time.hidden { - top: -2em; -} - -/* clock definitions */ -#clock { - font-size: 96px; - font-family: lcdbold; - color: #ffd204; - -webkit-text-fill-color: #ffd204; - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: black; - transition: top 0.3s; -} - -#clock.hidden { - top: -2em; -} -#clock.stopped { - color: red; - -webkit-text-fill-color: #c41425; -} -#clock.armed { - color: blue; - -webkit-text-fill-color: #0066b3; -} - -/* list */ -#list { - background-color: #ffd204; - opacity: 1; - transition: opacity 0.3s; -} -#list.hidden { - opacity: 0; -} -#list .header { - text-align: center; -} -#list .cell { - padding-left: 3vh; -} - -/* lowThird definitions */ -#lowThird { - background-color: #ffd204; - background-size: cover; - position: absolute; - height: 30vh; - padding: 2vh 5vw; - color: #6f2c91; - box-sizing: border-box; - transition: bottom 0.3s; -} - -#lowThird.hidden { - bottom: -30vh; -} - -#lowThird .line1 { - font-weight: bold; -} - -/* ticker */ -#twitter { - font-size: 6vh; - padding: 1em; - background-color: #0066b3; - color: white; - transition: bottom 0.3s; -} - -#twitter.hidden { - bottom: -4em; -} - -#twitter .tweet { - font-size: 6vh; -} - -#twitter .author { - font-weight: bold; -} - -#twitter .message { -} \ No newline at end of file diff --git a/themes/default.png b/themes/default.png deleted file mode 100644 index a92a91b..0000000 Binary files a/themes/default.png and /dev/null differ diff --git a/themes/fll-rtl.css b/themes/fll/fll-rtl.css similarity index 76% rename from themes/fll-rtl.css rename to themes/fll/fll-rtl.css index 49d22e3..1d1162b 100644 --- a/themes/fll-rtl.css +++ b/themes/fll/fll-rtl.css @@ -13,7 +13,7 @@ body { right: -20vw; transform: translate(-20vw); background-color: darkblue; - font-family: lcdbold; + font-family: lcdbold, sans-serif; color: white; transition: transform 0.3s; height: 10vh; @@ -30,7 +30,7 @@ body { position: absolute; left: -2.5vh; top: 0; - border: 2px solid black; + border-style: solid; box-sizing: border-box; border-width: 10vh 0 0 2.5vh; border-color: darkblue transparent; @@ -50,7 +50,7 @@ body { left: -20vw; transform: translate(20vw); background-color: darkblue; - font-family: lcdbold; + font-family: lcdbold, sans-serif; color: white; transition: transform 0.3s; height: 10vh; @@ -69,7 +69,7 @@ body { position: absolute; right: -2.5vh; top: 0; - border: 2px solid black; + border-style: solid; box-sizing: border-box; border-width: 0 2.5vh 10vh 0; border-color: darkblue transparent; @@ -91,7 +91,7 @@ body { /* list */ #list { - background-image: url(fll_list_bkg-rtl.png); + background-image: url(fll_list_bkg.png); background-size: 100% 100%; color: black; opacity: 1; @@ -103,6 +103,15 @@ body { padding: 4vw; } +#list, #list > * { + -moz-transform: scaleX(-1); + -o-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: "FlipH"; + -ms-filter: "FlipH"; +} + #list.hidden { opacity: 0; } @@ -128,7 +137,7 @@ body { /* lowThird definitions */ #lowThird { - background-image: url(fll_lowThird_bkg-rtl.png); + background-image: url(fll_lowThird_bkg.png); background-size: cover; color: black; height: 26vh; @@ -137,6 +146,16 @@ body { padding-right: 22vw; transition: transform 0.3s; } + +#lowThird, #lowThird > * { + -moz-transform: scaleX(-1); + -o-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: "FlipH"; + -ms-filter: "FlipH"; +} + #lowThird.hidden { transform: translateY(120%); } @@ -149,7 +168,7 @@ body { /* used ceaser to create custom easing functions: http://matthewlein.com/ceaser/ */ #lowThird .line1 { /*background-color: darkblue;*/ - width: 80%; + width: 72%; font-size: 8vh; height: 10vh; line-height: 10vh; @@ -157,7 +176,7 @@ body { #lowThird .line2 { /*background-color: crimson;*/ - width: 70%; + width: 72%; font-size: 5vh; height: 8vh; line-height: 8vh; @@ -172,12 +191,24 @@ body { transition: bottom 0.3s; } +#twitter, #twitter .tweet { + -moz-transform: scaleX(-1); + -o-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: "FlipH"; + -ms-filter: "FlipH"; +} + #twitter.hidden { bottom: -4em; } #twitter .tweet { font-size: 6vh; + display: inline-block; + padding-right: inherit !important; + padding-left: 1.5em; } #twitter .author { diff --git a/themes/fll.css b/themes/fll/fll.css similarity index 97% rename from themes/fll.css rename to themes/fll/fll.css index 52e1228..5026a5a 100644 --- a/themes/fll.css +++ b/themes/fll/fll.css @@ -1,8 +1,13 @@ body { font-family: verdana, helvetica, sans-serif; + visibility: visible; } + + + /* time definitions */ + #time { left: -20vw; transform: translate(20vw); @@ -16,6 +21,7 @@ body { padding-left: 3vh; padding-right: 1vh; } + #time::after { content: ''; width: 2.5vh; @@ -34,7 +40,9 @@ body { transform: translate(0); } + /* clock */ + #clock { right: -20vw; transform: translate(-20vw); @@ -71,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%; @@ -91,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; @@ -111,7 +128,9 @@ body { border: #FFD204 1px solid; } + /* lowThird definitions */ + #lowThird { background-image: url(fll_lowThird_bkg.png); background-size: cover; @@ -122,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%; @@ -148,7 +171,9 @@ body { line-height: 8vh; } + /* ticker */ + #twitter { font-size: 6vh; padding: 0.2em; @@ -169,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_list_bkg.png b/themes/fll/fll_list_bkg.png similarity index 100% rename from themes/fll_list_bkg.png rename to themes/fll/fll_list_bkg.png diff --git a/themes/fll_lowThird_bkg.png b/themes/fll/fll_lowThird_bkg.png similarity index 100% rename from themes/fll_lowThird_bkg.png rename to themes/fll/fll_lowThird_bkg.png 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 diff --git a/themes/fll_list_bkg-rtl.png b/themes/fll_list_bkg-rtl.png deleted file mode 100644 index 08451a8..0000000 Binary files a/themes/fll_list_bkg-rtl.png and /dev/null differ diff --git a/themes/fll_lowThird_bkg-rtl.png b/themes/fll_lowThird_bkg-rtl.png deleted file mode 100644 index 90ee973..0000000 Binary files a/themes/fll_lowThird_bkg-rtl.png and /dev/null differ diff --git a/themes/readme.md b/themes/readme.md index bdc385c..2c0a797 100644 --- a/themes/readme.md +++ b/themes/readme.md @@ -1,12 +1,12 @@ Themes ====== -default +rednblue ----- -![default theme screenshot](default.png) +![rednblue theme screenshot](rednblue/rednblue.png) -rednblue +rednblue-plus ----- -![rednblue theme screenshot](rednblue.png) \ No newline at end of file +![rednblue-plus theme screenshot](rednblue-plus/rednblue-plus.png) diff --git a/themes/rednblue-plus/fonts/benchnine/benchnine-bold-webfont.woff b/themes/rednblue-plus/fonts/benchnine/benchnine-bold-webfont.woff new file mode 100644 index 0000000..95ecc0a Binary files /dev/null and b/themes/rednblue-plus/fonts/benchnine/benchnine-bold-webfont.woff differ diff --git a/themes/rednblue-plus/fonts/benchnine/benchnine-bold-webfont.woff2 b/themes/rednblue-plus/fonts/benchnine/benchnine-bold-webfont.woff2 new file mode 100644 index 0000000..35c7c54 Binary files /dev/null and b/themes/rednblue-plus/fonts/benchnine/benchnine-bold-webfont.woff2 differ diff --git a/themes/rednblue-plus/fonts/benchnine/benchnine-light-webfont.woff b/themes/rednblue-plus/fonts/benchnine/benchnine-light-webfont.woff new file mode 100644 index 0000000..e2c3df6 Binary files /dev/null and b/themes/rednblue-plus/fonts/benchnine/benchnine-light-webfont.woff differ diff --git a/themes/rednblue-plus/fonts/benchnine/benchnine-light-webfont.woff2 b/themes/rednblue-plus/fonts/benchnine/benchnine-light-webfont.woff2 new file mode 100644 index 0000000..5acbad9 Binary files /dev/null and b/themes/rednblue-plus/fonts/benchnine/benchnine-light-webfont.woff2 differ diff --git a/themes/rednblue-plus/fonts/benchnine/benchnine-regular-webfont.woff b/themes/rednblue-plus/fonts/benchnine/benchnine-regular-webfont.woff new file mode 100644 index 0000000..198a3e7 Binary files /dev/null and b/themes/rednblue-plus/fonts/benchnine/benchnine-regular-webfont.woff differ diff --git a/themes/rednblue-plus/fonts/benchnine/benchnine-regular-webfont.woff2 b/themes/rednblue-plus/fonts/benchnine/benchnine-regular-webfont.woff2 new file mode 100644 index 0000000..47a3b03 Binary files /dev/null and b/themes/rednblue-plus/fonts/benchnine/benchnine-regular-webfont.woff2 differ diff --git a/themes/rednblue-plus/fonts/benchnine/benchnine.css b/themes/rednblue-plus/fonts/benchnine/benchnine.css new file mode 100644 index 0000000..5b55931 --- /dev/null +++ b/themes/rednblue-plus/fonts/benchnine/benchnine.css @@ -0,0 +1,36 @@ +/*! Generated by Font Squirrel (https://www.fontsquirrel.com) on August 7, 2017 */ + + + +@font-face { + font-family: 'benchninebold'; + src: url('benchnine-bold-webfont.woff2') format('woff2'), + url('benchnine-bold-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; + +} + + + + +@font-face { + font-family: 'benchninelight'; + src: url('benchnine-light-webfont.woff2') format('woff2'), + url('benchnine-light-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; + +} + + + + +@font-face { + font-family: 'benchnineregular'; + src: url('benchnine-regular-webfont.woff2') format('woff2'), + url('benchnine-regular-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; + +} \ No newline at end of file diff --git a/themes/rednblue-plus/readme.md b/themes/rednblue-plus/readme.md new file mode 100644 index 0000000..151432b --- /dev/null +++ b/themes/rednblue-plus/readme.md @@ -0,0 +1,17 @@ +# rednblue-plus theme + +use it with the `css` module in the config like this: + + ... + 'css': { + href: [ + 'themes/rednblue-plus/rednblue-plus.css', + // 'themes/rednblue-plus/rednblue-plus-mod-rtl.css', + // 'themes/rednblue-plus/rednblue-plus-mod-opaque.css' + ], + }, + ... + +The rtl modifier css can be added for rtl text support. + +The opaque modifier can be added to make everything fully opaque instead of partially transparent. This can be useful when working with a chroma-key. diff --git a/themes/rednblue-plus/rednblue-plus-mod-opaque.css b/themes/rednblue-plus/rednblue-plus-mod-opaque.css new file mode 100644 index 0000000..a213c15 --- /dev/null +++ b/themes/rednblue-plus/rednblue-plus-mod-opaque.css @@ -0,0 +1,61 @@ +/** + * this is an opaque modifier for the rednblue-plus theme + * it is designed to be included with the core theme file + * + * this makes all the transparent backgrounds fully opaque + * so it can be used with chromakeying + */ + +/* time definitions */ +@media screen { + #time::before { + background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(214,214,214,1) 100%); + } +} + +/* clock */ +@media screen { + #clock::before { + background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(214,214,214,1) 100%); + } + #clock.stopped::before { + background: linear-gradient(to bottom, rgba(237,20,61,1) 0%,rgba(237,20,61,1) 100%); + } +} + +/* table definitions */ +@media screen { + #table { + background: linear-gradient(to right, rgba(0,0,139,1) 0%,rgba(0,0,139,1) 100%); + } + #table thead tr { + background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(214,214,214,1) 100%); + } +} + +/* list */ +@media screen { + #list .list-row { + background: linear-gradient(to right, rgba(0,0,139,1) 0%,rgba(0,0,139,1) 100%); + } + #list .list-head.list-row { + background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(214,214,214,1) 100%); + } + #list.hidden .list-cell.list-row-even { + opacity: 1; + } + #list.hidden .list-cell.list-row-odd { + opacity: 1; + } +} + +/* lowThird definitions */ +@media screen { + #lowThird .line1::before { + background: linear-gradient(to right, rgba(0,0,139,1) 0%,rgba(0,0,139,1) 100%); + } + + #lowThird .line2::before { + background: linear-gradient(to right, rgba(237,20,61,1) 0%,rgba(237,20,61,1) 100%); + } +} diff --git a/themes/rednblue-plus/rednblue-plus-mod-rtl.css b/themes/rednblue-plus/rednblue-plus-mod-rtl.css new file mode 100644 index 0000000..e07e449 --- /dev/null +++ b/themes/rednblue-plus/rednblue-plus-mod-rtl.css @@ -0,0 +1,138 @@ +/** + * this is an rtl modifier for the rednblue-plus theme + * it is designed to be included with the core theme file + * + * this all text directions rtl, as well as gradients + */ + +body { + direction: rtl; +} + +/* time definitions */ +@media screen { + #time { + left: auto !important; + right: -11em; + transform: translate(-10em); + padding-left: 0.5em; + padding-right: 1.25em; + text-align: left; + } + #time::before { + transform: skew(20deg); + } + #time::after { + background: linear-gradient(to left, + transparent 0%, + transparent 84%, + crimson 85%, + crimson 89%, + white 90%, + white 94%, + darkblue 95%, + darkblue 100% + ); + transform: skew(20deg); + border-radius: 0.5em / 1em; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } +} + +/* clock */ +@media screen { + #clock { + left: -11em; + right: auto !important; + transform: translate(10em); + padding-left: 0; + padding-right: 0.5em; + text-align: right; + } + + #clock::before { + transform: skew(20deg); + } +} + +/* table definitions */ +@media screen { + #table { + background: linear-gradient(to left, rgba(0,0,139,0.9) 0%,rgba(0,0,139,0.7) 100%); + } + #table thead tr { + background: linear-gradient(to left, rgba(255,255,255,1) 0%,rgba(214,214,214,0.8) 100%); + } +} + +/* list */ +@media screen { + #list .list-row { + background: linear-gradient(to left, rgba(0,0,139,0.9) 0%,rgba(0,0,139,0.7) 100%); + transform: skew(20deg); + } + #list .list-cell { + text-align: right; + } + #list .list-cell.number { + text-align: left; + } + #list.hidden .list-row.list-row-even { + transform: translateX(120vw) scaleY(0.1); + } + #list.hidden .list-cell.list-row-even { + 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 { + transform: translateX(-120vw) scaleY(0.1); + } +} + +/* lowThird definitions */ +@media screen { + #lowThird .line { + left: auto; + right: -4vh; + padding-left: 0; + padding-right: 8vh; + } + #lowThird.hidden .line { + transform: translate(120%); + } + + #lowThird .line1::before { + left: auto; + right: 0; + background: linear-gradient(to left, rgba(0,0,139,0.9) 0%,rgba(0,0,139,0.7) 100%); + transform: skew(20deg); + } + + #lowThird .line2::before { + left: auto; + right: 0; + background: linear-gradient(to left, rgba(237,20,61,0.9) 0%,rgba(237,20,61,0.7) 100%); + transform: skew(20deg); + } +} + +/* ticker */ +@media screen { + #twitter, #twitter .tweet { + -moz-transform: scaleX(-1); + -o-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: "FlipH"; + -ms-filter: "FlipH"; + } + + #twitter .tweet { + display: inline-block; + padding-right: inherit !important; + padding-left: 1.5em; + } +} diff --git a/themes/rednblue-plus/rednblue-plus.css b/themes/rednblue-plus/rednblue-plus.css new file mode 100644 index 0000000..7cc6cdd --- /dev/null +++ b/themes/rednblue-plus/rednblue-plus.css @@ -0,0 +1,352 @@ +@import url('fonts/benchnine/benchnine.css'); + +/** + * 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: 15vh auto; + overflow: hidden; + font-size: 5vh; + 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, + #table td { + border-bottom: 1px solid rgba(255,255,255,0.5); + } + #table.hidden { + opacity: 0; + } + #table.visible { + opacity: 1; + } +} + +/* 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 { + } +} diff --git a/themes/rednblue-plus/rednblue-plus.png b/themes/rednblue-plus/rednblue-plus.png new file mode 100644 index 0000000..d349f82 Binary files /dev/null and b/themes/rednblue-plus/rednblue-plus.png differ diff --git a/themes/rednblue-rtl.css b/themes/rednblue-rtl.css deleted file mode 100644 index 0180aae..0000000 --- a/themes/rednblue-rtl.css +++ /dev/null @@ -1,280 +0,0 @@ -@import url('../fonts/lcd-bold.css'); - -body { - font-family: verdana, helvetica, sans-serif; - direction: rtl; -} - -/* time definitions */ -#time { - left: auto !important; - right: 0.5em; -} - -#time { - right: -20vw; - transform: translate(-20vw); - background-color: darkblue; - font-family: lcdbold, sans-serif; - color: white; - transition: transform 0.3s; - height: 10vh; - font-size: 8vh; - line-height: 12vh; - padding-right: 3vh; - padding-left: 1vh; -} -#time::after { - content: ''; - width: 2.5vh; - display: block; - height: 10vh; - position: absolute; - left: -2.5vh; - top: 0; - box-sizing: border-box; - border-style: solid; - border-width: 10vh 0 0 2.5vh; - border-color: darkblue transparent; -} - -#time.hidden { - transform: translate(0); -} - -/* clock */ -#clock { - left: 0.5em; - right: auto !important; -} - -#clock { - left: -20vw; - transform: translate(20vw); - background-color: darkblue; - font-family: lcdbold, sans-serif; - color: white; - transition: transform 0.3s; - height: 10vh; - font-size: 8vh; - line-height: 12vh; - width: 20vh; - padding-left: 3vh; - text-align: left; -} - -#clock::before { - content: ''; - width: 2.5vh; - display: block; - height: 10vh; - position: absolute; - right: -2.5vh; - top: 0; - box-sizing: border-box; - border-style: solid; - border-width: 0 2.5vh 10vh 0; - border-color: darkblue transparent; -} - -#clock.hidden { - transform: translate(0); -} - -#clock.stopped { - background-color: crimson; -} -#clock.stopped::before { - border-color: crimson transparent; -} -#clock.armed { - color: crimson; -} - -/* list */ -#list { - opacity: 1; - transition: opacity 0.3s; -} -#list.hidden { - opacity: 0; -} -#list .header { - text-align: center; - margin-bottom: 0.8vh; -} -#list .header span { - display: inline-block; - background-color: crimson; - color: white; - line-height: 7.2vh; - height: 7.2vh; - vertical-align: top; -} -#list .header span::before { - content: ''; - width: 4.8vh; - display: inline-block; - height: 7.2vh; - /*position: absolute;*/ - margin-right: -4.8vh; - top: 0; - box-sizing: border-box; - border-style: solid; - border-width: 0 1.8vh 7.2vh 0; - border-color: crimson transparent; -} -#list .header span::after { - content: ''; - width: 4.8vh; - display: inline-block; - height: 7.2vh; - /*position: absolute;*/ - margin-left: -4.8vh; - top: 0; - box-sizing: border-box; - border: solid; - border-width: 0 0 7.2vh 1.8vh; - border-color: crimson transparent; -} -#list .row { - height: 6.4vh; - font-size: 5.0vh; - background-color: darkblue; - color: white; - margin-bottom: 0.8vh; - position: relative; - line-height: 6.4vh; - transition: transform 0.3s; -} -#list.hidden .row { - transform: rotateX(90deg); -} -#list .row::before { - content: ''; - width: 1.6vh; - display: block; - height: 6.4vh; - position: absolute; - right: -1.6vh; - top: 0; - box-sizing: border-box; - border: solid; - border-width: 6.4vh 0 0 1.6vh; - border-color: transparent darkblue; -} -#list .row::after { - content: ''; - width: 1.6vh; - display: block; - height: 6.4vh; - position: absolute; - left: -1.6vh; - top: 0; - box-sizing: border-box; - border: solid; - border-width: 6.4vh 0 0 1.6vh; - border-color: darkblue transparent; -} -#list .cell { - padding-right: 3vh; -} - -/* table defenitions */ -#table { - color: white; - background: darkblue; - direction: rtl; -} - -#table td { - border: white 1px solid; -} - -/* lowThird definitions */ -#lowThird { - background: none; - height: 22vh; - box-sizing: border-box; -} -#lowThird .line { - color: white; - padding-right: 3vh; - transition: transform 0.3s; - transform: translate(0); - box-sizing: border-box; - position: relative; -} -#lowThird.hidden .line { - transform: translate(120%); -} - -/* used ceaser to create custom easing functions: http://matthewlein.com/ceaser/ */ -#lowThird .line1 { - background-color: darkblue; - width: 80%; - transition-timing-function: cubic-bezier(0.250, 0.100, 0.000, 1.000); - font-size: 8vh; - height: 10vh; - line-height: 10vh; -} -#lowThird .line1::after { - content: ''; - width: 2.5vh; - display: block; - height: 10vh; - position: absolute; - left: -2.5vh; - top: 0; - box-sizing: border-box; - border: solid; - border-width: 10vh 0 0 2.5vh; - border-color: darkblue transparent; -} - -#lowThird .line2 { - background-color: crimson; - 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::after { - content: ''; - width: 2vh; - display: block; - height: 8vh; - position: absolute; - left: -2vh; - top: 0; - box-sizing: border-box; - border: solid; - border-width: 8vh 0 0 2vh; - border-color: crimson transparent; -} - -/* ticker */ -#twitter { - font-size: 6vh; - padding: 0.2em; - background-color: darkblue; - color: white; - transition: bottom 0.3s; -} - -#twitter.hidden { - bottom: -4em; -} - -#twitter .tweet { - font-size: 6vh; -} - -#twitter .author { - font-weight: bold; -} - -#twitter .message { -} \ No newline at end of file diff --git a/themes/rednblue.png b/themes/rednblue.png deleted file mode 100644 index ac8cfd7..0000000 Binary files a/themes/rednblue.png and /dev/null differ diff --git a/themes/rednblue/readme.md b/themes/rednblue/readme.md new file mode 100644 index 0000000..3ea30c8 --- /dev/null +++ b/themes/rednblue/readme.md @@ -0,0 +1,14 @@ +# rednblue theme + +use it with the `css` module in the config like this: + + ... + 'css': { + href: [ + 'themes/rednblue/rednblue.css', + // 'themes/rednblue/rednblue-mod-rtl.css' + ] + }, + ... + +The rtl modifier css can be added for rtl text support. diff --git a/themes/rednblue/rednblue-mod-rtl.css b/themes/rednblue/rednblue-mod-rtl.css new file mode 100644 index 0000000..aacf20f --- /dev/null +++ b/themes/rednblue/rednblue-mod-rtl.css @@ -0,0 +1,121 @@ +/** + * this is an rtl modifier for the rednblue theme + * it is designed to be included with the core theme file + * + * this all text directions rtl, as well as gradients + */ + +body { + direction: rtl; +} + +/* time definitions */ +#time { + left: auto !important; + right: 0.5em; +} + +#time { + right: -20vw; + transform: translate(-20vw); + padding-left: 1vh; + padding-right: 3vh; +} +#time::after { + right: auto; + left: -2.5vh; + border-width: 10vh 0 0 2.5vh; +} + +/* clock */ +#clock { + left: 0.5em; + right: auto !important; +} + +#clock { + left: -20vw; + transform: translate(20vw); + padding-left: 3vh; + padding-right: 0; + text-align: left; +} + +#clock::before { + left: auto; + right: -2.5vh; + border-width: 0 2.5vh 10vh 0; +} + +/* list */ +#list .list-row::before { + left: auto; + right: -1.6vh; + border-width: 6.4vh 0 0 1.6vh; +} +#list .list-row::after { + right: auto; + left: -1.6vh; + border-width: 6.4vh 0 0 1.6vh; +} +#list .list-cell { + padding-left: 0; + padding-right: 3vh; +} +#list .list-cell.number { + text-align: right; + padding-right: 0; + padding-left: 3vh; +} +#list .list-head.list-row::before { + margin-left: 0; + margin-right: -2.8vh; + border-width: 0 1.8vh 7.2vh 0; +} +#list .list-head.list-row::after { + margin-left: -2.8vh; + margin-right: 0; + border-width: 0 0 7.2vh 1.8vh; +} + +/* table defenitions */ +#table { + direction: rtl; +} + +/* lowThird definitions */ +#lowThird .line { + padding-left: 0; + padding-right: 3vh; +} +#lowThird.hidden .line { + transform: translate(120%); +} + +#lowThird .line1::after { + right: auto; + left: -2.5vh; + border-width: 10vh 0 0 2.5vh; +} + +#lowThird .line2::after { + right: auto; + left: -2vh; + border-width: 8vh 0 0 2vh; +} + +/* ticker */ +#twitter, #twitter .tweet { + -moz-transform: scaleX(-1); + -o-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: "FlipH"; + -ms-filter: "FlipH"; +} + +#twitter .tweet { + display: inline-block; + padding-right: inherit !important; + padding-left: 1.5em; +} diff --git a/themes/rednblue.css b/themes/rednblue/rednblue.css similarity index 82% rename from themes/rednblue.css rename to themes/rednblue/rednblue.css index 6063e08..7344ff8 100644 --- a/themes/rednblue.css +++ b/themes/rednblue/rednblue.css @@ -1,5 +1,12 @@ +@import url('../fonts/lcd-bold.css'); + body { font-family: verdana, helvetica, sans-serif; + visibility: visible; +} + +img.emojione { + height: 1em; } /* time definitions */ @@ -7,9 +14,9 @@ body { left: -20vw; transform: translate(20vw); background-color: darkblue; - font-family: lcdbold; + font-family: lcdbold, sans-serif; color: white; - transition: transform 0.3s; + transition: transform 0.3s, visibility 0.3s; height: 10vh; font-size: 8vh; line-height: 12vh; @@ -39,9 +46,9 @@ body { right: -20vw; transform: translate(-20vw); background-color: darkblue; - font-family: lcdbold; + font-family: lcdbold, sans-serif; color: white; - transition: transform 0.3s; + transition: transform 0.3s, visibility 0.3s; height: 10vh; font-size: 8vh; line-height: 12vh; @@ -81,50 +88,14 @@ body { /* list */ #list { opacity: 1; - transition: opacity 0.3s; + transition: all 0.3s; + margin: 15vh auto; + font-size: 5vh; } #list.hidden { opacity: 0; } -#list .header { - text-align: center; - margin-bottom: 0.8vh; -} -#list .header span { - display: inline-block; - background-color: crimson; - color: white; - line-height: 7.2vh; - height: 7.2vh; - vertical-align: top; -} -#list .header span::before { - content: ''; - width: 4.8vh; - display: inline-block; - height: 7.2vh; - /*position: absolute;*/ - margin-left: -4.8vh; - top: 0; - border: 2px solid black; - box-sizing: border-box; - border-width: 0 0 7.2vh 1.8vh; - border-color: crimson transparent; -} -#list .header span::after { - content: ''; - width: 4.8vh; - display: inline-block; - height: 7.2vh; - /*position: absolute;*/ - margin-right: -4.8vh; - top: 0; - border: 2px solid black; - box-sizing: border-box; - border-width: 0 1.8vh 7.2vh 0; - border-color: crimson transparent; -} -#list .row { +#list .list-row { height: 6.4vh; font-size: 5.0vh; background-color: darkblue; @@ -134,10 +105,10 @@ body { line-height: 6.4vh; transition: transform 0.3s; } -#list.hidden .row { +#list.hidden .list-row { transform: rotateX(90deg); } -#list .row::before { +#list .list-row::before { content: ''; width: 1.6vh; display: block; @@ -150,7 +121,7 @@ body { border-width: 6.4vh 1.6vh 0 0; border-color: transparent darkblue; } -#list .row::after { +#list .list-row::after { content: ''; width: 1.6vh; display: block; @@ -163,14 +134,66 @@ body { border-width: 6.4vh 1.6vh 0 0; border-color: darkblue transparent; } -#list .cell { +#list .list-cell { + transform: scale(1); padding-left: 3vh; } +#list .list-cell.number { + text-align: right; + padding-left: 0; + padding-right: 3vh; +} + +#list .list-head { + text-align: center; + margin-bottom: 0.8vh; + margin-left: 7em; + margin-right: 7em; +} +#list .list-head.list-row { + display: inline-block; + background-color: crimson; + color: white; + line-height: 7.2vh; + height: 7.2vh; + vertical-align: top; +} +#list .list-head.list-row::before { + content: ''; + width: 4.8vh; + display: inline-block; + height: 7.2vh; + margin-left: -2.8vh; + top: 0; + border: 2px solid black; + box-sizing: border-box; + border-width: 0 0 7.2vh 1.8vh; + border-color: crimson transparent; +} +#list .list-head.list-row::after { + content: ''; + width: 4.8vh; + display: inline-block; + height: 7.2vh; + margin-right: -2.8vh; + top: 0; + border: 2px solid black; + box-sizing: border-box; + border-width: 0 1.8vh 7.2vh 0; + border-color: crimson transparent; +} /* table defenitions */ #table { + margin: 15vh auto; color: white; + border-collapse: collapse; background: darkblue; + font-size: 5vh; +} + +#table.hidden { + display: none; } #table td { @@ -186,7 +209,7 @@ body { #lowThird .line { color: white; padding-left: 3vh; - transition: transform 0.3s; + transition: transform 0.3s, visibility 0.3s; transform: translate(0); box-sizing: border-box; position: relative; @@ -247,7 +270,7 @@ body { padding: 0.2em; background-color: darkblue; color: white; - transition: bottom 0.3s; + transition: bottom 0.3s, visibility 0.3s; } #twitter.hidden { @@ -263,4 +286,4 @@ body { } #twitter .message { -} \ No newline at end of file +} diff --git a/themes/rednblue/rednblue.png b/themes/rednblue/rednblue.png new file mode 100644 index 0000000..6190631 Binary files /dev/null and b/themes/rednblue/rednblue.png differ