Introduction
Introduction Statistics Contact Development Disclaimer Help
add script - jscancer - Javascript crap (relatively small)
git clone git://git.codemadness.org/jscancer
Log
Files
Refs
README
LICENSE
---
commit ba166782d82d92a2dcf4ee22b96da2285874a4b3
parent 9ba8da523384de2bdf895531b8145f93441ceec9
Author: Hiltjo Posthuma <[email protected]>
Date: Thu, 15 Feb 2024 19:18:22 +0100
add script
Diffstat:
A narrowcasting/README | 27 +++++++++++++++++++++++++++
A narrowcasting/index.html | 48 +++++++++++++++++++++++++++++…
A narrowcasting/script.js | 619 +++++++++++++++++++++++++++++…
A narrowcasting/style.css | 237 +++++++++++++++++++++++++++++…
4 files changed, 931 insertions(+), 0 deletions(-)
---
diff --git a/narrowcasting/README b/narrowcasting/README
@@ -0,0 +1,27 @@
+Narrowcasting
+-------------
+
+This is a simple script for some "narrowcasting" screen.
+It allows to defined HTML elements with data attributes for their configuratio…
+The script will then handle the widgets and slides logic.
+
+
+Some features:
+
+* Support embedding of data in <iframe>'s and refresh using some timer.
+* Support embedding of data in <embed> and update using some timer.
+* Support updating parts of the screen data using XMLHttpRequest (AJAX) using
+ some timer.
+* Date / clock widget, format it with a strftime()-like syntax.
+ Supports any locale forthe weekday and month names.
+* Support embedded videos, automatically pausing and continueing them when it
+ skips to the next slide or looping them.
+* A mechanism to poll some file for changes using some timer. When this data
+ changes the page is reloaded (forcing also a cache flush). This is useful for
+ remotely updating the layouts or scripts.
+* Show a newsticker. This uses the JSON Feed format.
+ sfeed_json could be used to convert from RSS/Atom to this format. This data
+ could be updated using a cronjob.
+* Progressbar to show the slides remaining duration.
+* Hotkeys to skip slides, useful for debugging also.
+* Uses vanilla JS with no dependencies on frameworks, etc.
diff --git a/narrowcasting/index.html b/narrowcasting/index.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>Narrowcasting</title>
+<link rel="stylesheet" type="text/css" href="style.css" />
+<link rel="icon" type="image/png" href="favicon.png" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+</head>
+<body>
+
+<div class="screen check-updates" data-update="120000" data-url="data/check_up…
+ <div class="logo"></div>
+ <div class="topbar-right">
+ <span class="datetime time" data-format="%H:%M" data-update="6…
+ <span class="datetime date" data-format="<span>%A <b>%e %B</b>…
+ </div>
+
+ <div class="topbar"></div>
+
+ <div class="topbar-info-dashboard"></div>
+
+ <div class="slides">
+ <div class="slide slide-1" id="slide-1" data-displaynext="3000…
+ <!-- widgets slide 1 -->
+ <div class="widget xhr-content" data-url="data/1" data…
+ <div class="widget xhr-content" data-url="data/2" data…
+ <div class="widget xhr-content" data-url="data/3" data…
+
+ <div class="widget widget-lichess embed-content" data-…
+ <iframe src="https://lichess.org/training/fram…
+ </div>
+
+ <div class="news-ticker ticker1" data-url="data/news1.…
+ <div class="news-ticker ticker2" data-url="data/news2.…
+ </div>
+
+ <div class="slide slide-2" id="slide-2" data-displaynext="3000…
+ </div>
+
+ <div class="progressbar"></div>
+ </div>
+</div>
+<script type="text/javascript" src="script.js">
+</script>
+</body>
+</html>
diff --git a/narrowcasting/script.js b/narrowcasting/script.js
@@ -0,0 +1,619 @@
+// run atleast once, then every n milliseconds.
+// if n is 0 just run once.
+function updateevery(n, fn) {
+ // schedule in parallel now.
+ setTimeout(function() {
+ fn();
+ }, 0);
+ if (!n)
+ return null;
+ return setInterval(fn, n);
+}
+
+function pad0(n) {
+ return (parseInt(n) < 10 ? "0" : "") + n.toString();
+}
+
+function padspace(n) {
+ return (parseInt(n) < 10 ? " " : "") + n.toString();
+}
+
+// dutch weekdays and months.
+//var strftime_weekdays = [ "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donde…
+//var strftime_months = [ "Januari", "Februari", "Maart", "April", "Mei", "Ju…
+
+// subset of strftime()
+function strftime(fmt, d) {
+ //var locale = locale || navigator.language || "en";
+ var locale = "nl-NL"; // dutch
+ d = d || new Date();
+
+ var mon = d.getMonth(); // starts at 0
+ var day = d.getDay(); // weekday, starts at 0 (sunday).
+
+ var s = fmt;
+ s = s.replace(/%Y/g, d.getFullYear().toString());
+ s = s.replace(/%m/g, pad0(mon + 1));
+ s = s.replace(/%d/g, pad0(d.getDate()));
+ s = s.replace(/%e/g, padspace(d.getDate()));
+ s = s.replace(/%H/g, pad0(d.getHours()));
+ s = s.replace(/%M/g, pad0(d.getMinutes()));
+ s = s.replace(/%S/g, pad0(d.getSeconds()));
+
+ s = s.replace(/%A/g, (new Intl.DateTimeFormat(locale, { weekday: "long…
+ s = s.replace(/%a/g, (new Intl.DateTimeFormat(locale, { weekday: "shor…
+ s = s.replace(/%B/g, (new Intl.DateTimeFormat(locale, { month: "long" …
+ s = s.replace(/%b/g, (new Intl.DateTimeFormat(locale, { month: "short"…
+
+ //s = s.replace(/%A/g, strftime_weekdays[day]); // full weekday name
+ //s = s.replace(/%a/g, strftime_weekdays[day].substring(0, 3)); // abb…
+ //s = s.replace(/%B/g, strftime_months[mon]); // full month name
+ //s = s.replace(/%b/g, strftime_months[mon].substring(0, 3)); // abbre…
+
+ return s;
+}
+
+// XMLHttpRequest helper function.
+function xhr(url, fn, timeout) {
+ var x = new(XMLHttpRequest);
+ x.open("get", url, true); // async
+ x.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ x.timeout = parseInt(timeout || 10000); // default: 10 seconds
+ x.onreadystatechange = function () {
+ if (x.readyState != 4)
+ return;
+ fn(x);
+ };
+ var data = "";
+ x.send(data);
+}
+
+// find direct descendent child element with a certain classname.
+function getdirectchilds(parent, classname) {
+ var els = [];
+
+ for (var i = 0; i < parent.children.length; i++) {
+ var el = parent.children[i];
+ if (el.classList.contains(classname))
+ els.push(el);
+ }
+
+ return els;
+}
+
+// news tickers.
+var tickerels = document.getElementsByClassName("news-ticker");
+var tickers = [];
+for (var i = 0; i < tickerels.length; i++) {
+ var url = tickerels[i].getAttribute("data-url") || "";
+ if (url == "")
+ continue;
+
+ // bind element to context
+ var t = (function(tickerel, delay) {
+ var displayfn = function(ticker) {
+ var parent = ticker.el;
+ var items = ticker.items || [];
+ var counter = ticker.counter || 0;
+
+ var node = document.createElement("div");
+ node.innerText = items[counter] || "";
+ parent.appendChild(node); // add new.
+ counter = (counter + 1) % items.length;
+
+ ticker.counter = counter; // update counter
+
+ if (parent.children.length) {
+ // schedule to be removed.
+ setTimeout(function() {
+ if (parent.children.length)
+ parent.children[0].className =…
+ setTimeout(function() {
+ if (parent.children.length > 1)
+ parent.removeChild(par…
+ }, ticker.fadein);
+ }, ticker.display);
+ }
+ };
+
+ var processfn = function(x) {
+ var feed = JSON.parse(x.responseText || "");
+ var items = [];
+ var feeditems = feed.items || [];
+
+ for (var j = 0; j < feeditems.length; j++) {
+ var title = feeditems[j].title;
+ var ts = feeditems[j].date_published || "";
+ // if there is a timestamp prefix it in the ti…
+ if (ts.length) {
+ var d = new Date(Date.parse(ts));
+ title = strftime("%H:%M", d) + " " + t…
+ }
+ items.push(title);
+ }
+ ticker.items = items;
+ };
+
+ // ticker config / context.
+ var ticker = {
+ el: tickerel,
+ url: (tickerel.getAttribute("data-url") || ""),
+ display: parseInt(tickerel.getAttribute("data-displayn…
+ fadein: parseInt(tickerel.getAttribute("data-fadein"))…
+ update: parseInt(tickerel.getAttribute("data-update"))…
+ };
+
+ ticker.processfn = processfn;
+ ticker.displayfn = displayfn;
+
+ // reload RSS/Atom data.
+ var updater = function() {
+ xhr(ticker.url, function(x) {
+ ticker.processfn(x);
+
+ // reset and stop previous timer for cycling i…
+ if (ticker.displaytimer)
+ clearInterval(ticker.displaytimer);
+
+ ticker.counter = 0; // reset item counter
+ ticker.el.innerHTML = ""; // clear contents
+ ticker.displayfn(ticker); // immediately updat…
+
+ // display / cycle existing items.
+ ticker.displaytimer = setInterval(function() {…
+ });
+ };
+
+ ticker.updater = updater;
+ ticker.updatetimer = setInterval(updater, ticker.update); // u…
+ setTimeout(updater, delay); // small delay so the newstickers …
+
+ return ticker;
+ })(tickerels[i], 1000 * i);
+
+ tickers.push(t);
+}
+
+// elements showing simple HTML content in a placeholder, refresh using XMLHTT…
+var xhrcontentels = document.getElementsByClassName("xhr-content");
+for (var i = 0; i < xhrcontentels.length; i++) {
+ var xhrcontentel = xhrcontentels[i];
+ var url = xhrcontentel.getAttribute("data-url") || "";
+ if (url == "")
+ continue;
+
+ // bind element to context.
+ (function(bindel) {
+ var updatefn = function(config) {
+ var parent = config.el;
+ var curcontent = parent.childNodes.length ? parent.chi…
+ var newcontent = config.data || "";
+ // content changed.
+ if (curcontent === newcontent)
+ return;
+
+ // remove previous nodes.
+ while (parent.childNodes.length > 0)
+ parent.removeChild(parent.childNodes[0]);
+
+ // add nodes to force a transition.
+ var node = document.createElement("div");
+ node.innerHTML = newcontent;
+ if (config.animate !== "") {
+ node.classList.add("animate-once");
+ node.classList.add(config.animateclass);
+ }
+ parent.appendChild(node); // add new.
+ };
+
+ var processfn = function(x) {
+ var data = "";
+ if (x.status >= 200 && x.status < 400)
+ data = x.responseText || "";
+ else
+ data = ""; // "ERROR";
+ config.data = data;
+ };
+
+ // config / context.
+ var config = {
+ animateclass: bindel.getAttribute("data-animate-class"…
+ el: bindel,
+ processfn: processfn,
+ timeout: parseInt(bindel.getAttribute("data-timeout"))…
+ update: parseInt(bindel.getAttribute("data-update")) |…
+ updatefn: updatefn,
+ url: (bindel.getAttribute("data-url") || "")
+ };
+
+ // reload data.
+ var updater = function() {
+ xhr(config.url, function(x) {
+ // process data.
+ config.processfn(x);
+ // update and display data.
+ config.updatefn(config);
+ }, config.timeout);
+ };
+
+ setInterval(updater, config.update);
+ // run almost immediately once the first time.
+ setTimeout(updater, 1);
+ })(xhrcontentel);
+}
+
+// object or iframe elements that simply show some HTML and refresh in an inte…
+var embedcontentels = document.getElementsByClassName("embed-content");
+for (var i = 0; i < embedcontentels.length; i++) {
+ var embedcontentel = embedcontentels[i];
+
+ // must have one child node of type "object" or "iframe".
+ if (embedcontentel.children.length <= 0)
+ continue;
+
+ var child = embedcontentel.children[0];
+
+ // bind element to context.
+ (function(bindel, child) {
+ var url = "";
+ var type = "";
+ var tagname = child.tagName;
+ if (tagname === "OBJECT") {
+ url = child.data || "";
+ type = child.getAttribute("data-type") || "text/html";
+ } else if (tagname === "IFRAME") {
+ url = child.getAttribute("src") || "";
+ }
+
+ // config / context.
+ var config = {
+ el: bindel,
+ update: parseInt(bindel.getAttribute("data-update")) |…
+ url: url,
+ type: type
+ };
+
+ var updater;
+ if (tagname === "OBJECT") {
+ // reload data.
+ updater = function() {
+ var objects = Array.from(bindel.childNodes); /…
+
+ var object = document.createElement("object");
+ object.data = config.url; // reload
+ object.type = config.type;
+ object.style.visibility = "hidden";
+ object.onload = function() {
+ // quickly swap out the old object(s) …
+ // this prevents some flickering.
+ for (var j = 0; j < objects.length; j+…
+ bindel.removeChild(objects[j]);
+ this.style.visibility = "visible";
+ };
+ bindel.appendChild(object);
+ };
+ } else if (tagname === "IFRAME") {
+ // reload data.
+ updater = function() {
+ child.contentWindow.location.reload();
+ };
+ }
+
+ setInterval(updater, config.update);
+ // run almost immediately once the first time.
+ setTimeout(updater, 1);
+ })(embedcontentel, child);
+}
+
+// pause videos inside element.
+function pausevideos(el) {
+ var videos = el.getElementsByTagName("video");
+ for (var i = 0; i < videos.length; i++) {
+ videos[i].pause();
+ if ((videos[i].getAttribute("data-reset-on-pause") || "") === …
+ videos[i].currentTime = 0; // reset time / seek to sta…
+ }
+}
+
+// play / resume videos inside element.
+function playvideos(el) {
+ var videos = el.getElementsByTagName("video");
+ for (var i = 0; i < videos.length; i++) {
+ videos[i].muted = true; // mute audio by default.
+ if ((videos[i].getAttribute("data-reset-on-play") || "") === "…
+ videos[i].currentTime = 0; // reset time / seek to sta…
+ videos[i].play(); // NOTE: auto-play must be enabled by the cl…
+ }
+}
+
+// date / clocks.
+var dates = document.getElementsByClassName("datetime");
+for (var i = 0; i < dates.length; i++) {
+ var format = dates[i].getAttribute("data-format") || "";
+ var freq = dates[i].getAttribute("data-update") || 1000; // default: 1…
+
+ var fn = (function(el, freq, format) {
+ return function() {
+ el.innerHTML = strftime(format); // allow HTML in form…
+ };
+ })(dates[i], freq, format);
+ updateevery(freq, fn);
+}
+
+// init slides and timings.
+function slides_init(rootel) {
+ rootel = rootel || document;
+ var slides = {
+ current: 0,
+ prev: -1,
+ prevprev: -1,
+ slides: []
+ };
+
+ // find direct descendent element with class "slide".
+ var slideels = getdirectchilds(rootel, "slide");
+ for (var i = 0; i < slideels.length; i++) {
+ var attrtiming = slideels[i].getAttribute("data-displaynext") …
+ var timing = parseInt(attrtiming);
+ if (timing <= 0)
+ timing = 5000;
+
+ var slide = {
+ timing: timing,
+ el: slideels[i]
+ };
+ slides.slides.push(slide);
+ }
+ return slides;
+}
+
+function slides_showcurrent(slides) {
+ var el = slides.slides[slides.current].el;
+ if (el === null)
+ return;
+ el.classList.add("visible");
+ playvideos(el);
+}
+
+function slides_change(slides) {
+ if (typeof(slides.prev) !== "undefined")
+ slides.slides[slides.prev].elapsed = 0;
+ slides.slides[slides.current].elapsed = 0;
+
+ slides_showcurrent(slides);
+ if (slides.onchange)
+ slides.onchange(slides.prev, slides.prevprev); // current, prev
+
+ // completely hidden.
+ if (slides.prevprev !== -1) {
+ var el = slides.slides[slides.prevprev].el;
+ el.classList.remove("pause");
+ }
+
+ // pause / fade out.
+ if (slides.prev !== -1) {
+ var el = slides.slides[slides.prev].el;
+ el.classList.remove("visible");
+ el.classList.add("pause");
+ pausevideos(el);
+ }
+}
+
+function slides_go(slides, n) {
+ // out-of-bounds or the same: do nothing.
+ if (n < 0 || n >= slides.slides.length || n == slides.current)
+ return;
+ slides.prevprev = slides.prev;
+ slides.prev = slides.current;
+ slides.current = n;
+ slides_change(slides);
+}
+
+function slides_prev(slides) {
+ var n = slides.current - 1;
+ if (n < 0 && slides.slides.length)
+ n = slides.slides.length - 1;
+ slides_go(slides, n);
+ slides_change(slides);
+}
+
+function slides_next(slides) {
+ var n = slides.current + 1;
+ if (n >= slides.slides.length)
+ n = 0;
+ slides_go(slides, n);
+ slides_change(slides);
+}
+
+function slides_pause(slides) {
+ slides.paused = true;
+ clearTimeout(slides.timernextslide);
+ clearTimeout(slides.timercurrentslide);
+ pausevideos(slides.slides[slides.current].el);
+}
+
+function slides_play(slides) {
+ slides_continue(slides);
+}
+
+function slides_continue(slides) {
+ slides.paused = false;
+ slides_updater(slides);
+ slides_showcurrent(slides);
+}
+
+function slides_updater(slides) {
+ // need more than 1 slide to change it.
+ if (slides.slides.length <= 1)
+ return;
+ var fn = function() {
+ slides_next(slides);
+ var currentslide = slides.slides[slides.current];
+ var timing = currentslide.timing || 5000; // default: 5 seconds
+ timing -= (currentslide.elapsed || 0); // minus played time fo…
+ slides.timernextslide = setTimeout(fn, timing);
+ };
+ var currentslide = slides.slides[slides.current];
+ var timing = currentslide.timing || 5000; // default: 5 seconds
+ timing -= (currentslide.elapsed || 0); // minus played time for this s…
+ slides.timercurrentslide = setTimeout(fn, timing);
+}
+
+function progressbar_init(slides, progressbar) {
+ if (slides.slides.length <= 1)
+ return;
+
+ // config: show total progress or progress per slide.
+ var usetotalprogress = parseInt(progressbar.getAttribute("data-total-p…
+
+ function progressbar_update(slides) {
+ var currentslide = slides.slides[slides.current];
+ var total = currentslide.timing || 5000; // default: 5 seconds
+
+ if (usetotalprogress) {
+ total = 0;
+ for (var i = 0; i < slides.slides.length; i++) {
+ total += parseInt(slides.slides[i].timing) || …
+ }
+ }
+
+ currentslide.elapsed = currentslide.elapsed || 0;
+
+ var perfnow = window.performance.now()
+ slides.prevprogress = slides.prevprogress || 0;
+
+ if (!slides.paused) {
+ currentslide.elapsed += perfnow - slides.prevprogress;
+ }
+ slides.prevprogress = perfnow;
+
+ var elapsed = currentslide.elapsed;
+ if (usetotalprogress) {
+ // current slide progress + all finished previous ones.
+ for (var i = 0; i < slides.current; i++)
+ elapsed += parseInt(slides.slides[i].timing) |…
+ }
+
+ // generate linear gradient with ticks for the total progress.
+ if (usetotalprogress) {
+ var total = 0;
+ for (var i = 0; i < slides.slides.length; i++) {
+ total += parseInt(slides.slides[i].timing) || …
+ }
+
+ var pattern = [];
+ var timing = 0;
+ for (var i = 0; i < slides.slides.length; i++) {
+ timing += parseInt(slides.slides[i].timing) ||…
+ var percent = (timing / total) * 100.0;
+
+ pattern.push("rgba(255, 255, 255, 0.0) " + (Ma…
+
+ // don't show tick for last.
+ if (i !== slides.slides.length - 1) {
+ // tick color
+ pattern.push("rgba(255,255,255, 1.0) "…
+ pattern.push("rgba(255,255,255, 0.0) "…
+ }
+ }
+
+ // ticks gradient;
+ var gradient = "linear-gradient(90deg, " + pattern.joi…
+ // progress gradient.
+ var percent = (elapsed / total) * 100.0;
+ gradient += ", linear-gradient(90deg, rgba(255, 255, 2…
+ "%, rgba(255, 255, 255, 0) " + (percent + 0.1)…
+ "%, rgba(255, 255, 255, 0) 100%)" // actual pr…
+ progressbar.style.background = gradient;
+ progressbar.style.width = "100%";
+ } else {
+ var percent = (elapsed / total) * 100.0;
+ progressbar.style.width = percent + "%";
+ }
+ }
+
+ function progressbar_updater() {
+ var fn = function() {
+ progressbar_update(slides);
+ };
+ setInterval(fn, 16); // 16ms, update at ~60fps
+ }
+
+ progressbar_updater(slides);
+}
+
+// initialize slides, can be nested.
+var rootels = document.getElementsByClassName("slides") || [];
+for (var i = 0; i < rootels.length; i++) {
+ var rootel = rootels[i];
+
+ var slides = slides_init(rootel);
+ slides_play(slides);
+
+ /* progressbar: shows current slide progress */
+ var progressbars = getdirectchilds(rootel, "progressbar");
+ if (progressbars.length) // use first progressbar.
+ progressbar_init(slides, progressbars[0]);
+}
+
+/* mechanism to poll if screen data is updated and needs a full refresh
+ ignoring the cache. */
+var lasthash = null;
+var els = document.getElementsByClassName("check-updates");
+for (var i = 0; i < els.length; i++) {
+ var el = els[i];
+ var interval = parseInt(el.getAttribute("data-update"));
+ if (interval <= 0)
+ continue;
+ var url = el.getAttribute("data-url") || "";
+ if (url === "")
+ continue;
+
+ var fn = function(x) {
+ if (x.status >= 200 && x.status < 400) {
+ var newhash = x.responseText || "";
+ if (lasthash === null) {
+ lasthash = newhash;
+ } else if (newhash !== lasthash) {
+ // reload, ignore cache: works in Chrome and F…
+ window.location.reload(true);
+ }
+ }
+ };
+
+ setInterval(function() {
+ xhr(url, fn, 10000);
+ }, interval);
+ xhr(url, fn, 10000);
+
+ break;
+}
+
+window.addEventListener("keyup", function(e) {
+ switch (e.keyCode) {
+ case 32: // space: toggle pause/play.
+ if (slides.paused)
+ slides_continue(slides);
+ else
+ slides_pause(slides);
+ break;
+ case 37: // left arrow: previous slide.
+ slides_prev(slides);
+ break;
+ case 13: // return or right arrow next slide.
+ case 39:
+ slides_next(slides);
+ break;
+ case 49: // '1': go to slide 1
+ case 50: // '2': go to slide 2
+ case 51: // '3': go to slide 3
+ case 52: // '4': go to slide 4
+ case 53: // '5': go to slide 5
+ case 54: // '6': go to slide 6
+ case 55: // '7': go to slide 7
+ case 56: // '8': go to slide 8
+ case 57: // '9': go to slide 9
+ slides_go(slides, e.keyCode - 49);
+ break;
+ }
+}, false);
diff --git a/narrowcasting/style.css b/narrowcasting/style.css
@@ -0,0 +1,237 @@
+@keyframes fade-in {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+@keyframes fade-out {
+ 0% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ }
+}
+@keyframes news-slide-in {
+ 0% {
+ margin-left: 100%;
+ opacity: 0;
+ }
+ 100% {
+ margin-left: 0;
+ opacity: 1;
+ }
+}
+@keyframes news-slide-out {
+ 0% {
+ margin-left: 0;
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ margin-left: -100%;
+ }
+}
+body {
+ font-family: sans-serif;
+}
+html, body {
+ overflow: hidden;
+}
+h1 {
+ font-size: 120%;
+ font-weight: bold;
+ margin: 5px 0;
+ padding: 0;
+}
+ul {
+ margin: 0;
+ padding: 0;
+}
+iframe {
+ border: 0;
+}
+.news-ticker {
+ position: fixed;
+ background-color: #eee;
+ line-height: 90px;
+ height: 90px;
+ overflow: hidden;
+}
+.news-ticker div {
+ position: absolute;
+ padding: 0 0 0 5px;
+ line-height: 90px;
+ height: 90px;
+ animation: ease-out news-slide-in 1s;
+}
+
+.news-ticker div.out {
+ animation: ease-out news-slide-out 2s;
+}
+.ticker1 {
+ z-index: 9999;
+ bottom: 90px;
+ left: 0;
+ right: 0;
+ font-size: 40px;
+ background-color: #333;
+ color: #fff;
+ font-weight: bold;
+}
+.ticker2 {
+ z-index: 9999;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-size: 40px;
+ background-color: #555;
+ color: #fff;
+ font-weight: bold;
+}
+.logo {
+ width: 854px;
+ background-image: url('logo.png');
+ background-repeat: no-repeat;
+ background-position: center left;
+ background-size: auto 160px;
+ height: 180px;
+ position: absolute;
+ top: 0;
+ left: 25px;
+ z-index: 999;
+}
+.screen {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+
+ background-repeat: no-repeat;
+}
+.topbar {
+ z-index: 997;
+
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 115px;
+ right: 0;
+ background-color: #333;
+}
+.topbar-right {
+ z-index: 999;
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 115px;
+ background-color: #333;
+ background-repeat: no-repeat;
+ text-align: left;
+}
+
+.topbar-info-dashboard {
+ z-index: 999;
+ position: absolute;
+ top: 0;
+ width: 343px;
+ left: 100px;
+ height: 158px;
+ background-image: url('img/image.png');
+ background-repeat: no-repeat;
+ text-align: left;
+}
+
+.date {
+ float: right;
+ color: #fff;
+ font-size: 60px;
+ line-height: 115px;
+ padding-right: 70px;
+ white-space: nowrap;
+}
+.time {
+ margin-left: 50px;
+ padding-right: 50px;
+ float: right;
+ color: #fff;
+ font-weight: bold;
+ font-size: 90px;
+ line-height: 115px;
+ height: 115px;
+}
+.slide {
+ display: none;
+ background-repeat: no-repeat;
+ /* default background color, must be set for overlapping slides for tr…
+ /*background-color: #fff;*/
+}
+
+body > .screen > .slides > .slide {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+}
+body > .screen > .slides > .slide-2 {
+ background-color: #333;
+}
+
+.visible {
+ z-index: 995; /* visible has more preference over paused */
+ display: block;
+
+ animation: ease-in fade-in 1s;
+ animation-play-state: running;
+}
+
+.pause {
+ z-index: 990;
+ display: block;
+ opacity: 0;
+
+ animation: ease-out fade-out 1s;
+ animation-play-state: running;
+}
+
+.animate-once {
+ animation-iteration-count: 1;
+}
+.progressbar {
+ z-index: 9999;
+ position: absolute;
+ bottom: 0;
+ height: 3px;
+ left: 0;
+ width: 0%;
+ background-color: #fff;
+ opacity: 1.0 !important;
+}
+
+.widget {
+ padding: 0;
+ margin: 0;
+ color: #333;
+ font-size: 14pt;
+}
+.widget-header {
+ font-size: 30px;
+ font-weight: bold;
+ background-repeat: no-repeat;
+ color: #fff;
+ line-height: 60px;
+ padding: 0 10px;
+ text-transform: uppercase;
+}
+.widget-body {
+ padding: 5px 10px;
+}
+.widget-body ul {
+ padding: 0 20px;
+}
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.