Last active
June 27, 2017 16:34
-
-
Save adamabernathy/4f869da2251eaf92c49a1667d2b75ab3 to your computer and use it in GitHub Desktop.
Scrolling Weather Ticker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Scrolling Weather Ticker</title> | |
<style> | |
@-webkit-keyframes ticker { | |
0% { | |
-webkit-transform: translate3d(0, 0, 0); | |
transform: translate3d(0, 0, 0); | |
visibility: visible; | |
} | |
100% { | |
-webkit-transform: translate3d(-100%, 0, 0); | |
transform: translate3d(-100%, 0, 0); | |
} | |
} | |
@keyframes ticker { | |
0% { | |
-webkit-transform: translate3d(0, 0, 0); | |
transform: translate3d(0, 0, 0); | |
visibility: visible; | |
} | |
100% { | |
-webkit-transform: translate3d(-100%, 0, 0); | |
transform: translate3d(-100%, 0, 0); | |
} | |
} | |
/* Ticker container */ | |
.ticker-wrapper { | |
position: fixed; | |
width: 100%; | |
overflow: hidden; | |
height: 4rem; | |
background-color: rgba(40, 44, 52, 0.9); | |
padding-left: 100%; | |
padding-bottom: 1em; | |
} | |
/* Ticker item list container */ | |
.ticker { | |
display: inline-block; | |
height: 4em; | |
line-height: 4em; | |
white-space: nowrap; | |
padding-right: 100%; | |
-webkit-animation-iteration-count: infinite; | |
animation-iteration-count: infinite; | |
-webkit-animation-timing-function: linear; | |
animation-timing-function: linear; | |
-webkit-animation-name: ticker; | |
animation-name: ticker; | |
-webkit-animation-duration: 30s; | |
animation-duration: 30s; | |
} | |
/* Ticker items */ | |
.ticker-item { | |
display: inline-block; | |
padding: 0 2rem; | |
font-size: 2rem; | |
color: rgba(129, 195, 118, 1); | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Simple weather ticker</h1> | |
<p>This application demonstrates how to use the SynopticLabs Latest API with modern ES6 JavaScript.</p> | |
<div id="app-container" class="ticker-wrapper"> | |
<!-- Don't put anything here --> | |
</div> | |
</body> | |
<!-- Include the fetch() polyfill just in case legacy browsers are in play --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js"></script> | |
<script> | |
(function () { | |
'use strict'; | |
// While this script uses ES6 syntax and tricks, you can easily convert it to ES5 for | |
// compatability if needed with Babel at https://babeljs.io/ . | |
let state = { // Application state controller. | |
haveData: false, | |
api: { | |
apiBaseURL: 'https://api.mesowest.net/v2/', | |
service: 'stations/latest', | |
// Any valid SL Latest API argument can be used here. For this case we are | |
// just using three weather stations. You could use 'network' instead to see | |
// a group of stations; i.e. instead of 'stid' use 'network=153' | |
parameters: { token: 'dev', stid: 'wbb,hol,kslc', units: 'english' }, | |
requestURL: '' | |
}, | |
tickerRefreshInterval: 60000 // in milliseconds so 1 sec = 1000ms. | |
}; | |
// Application storage container. | |
let store = {}; | |
worker(state.api.service, state.api.parameters); | |
setInterval(() => { | |
removeElementById('__scroll-items'); | |
worker(state.api.service, state.api.parameters); | |
}, state.tickerRefreshInterval); | |
/** | |
* Main worker function. Requests data from webservice then controls the application update. | |
* @param {string} baseURL - Base URL of web service to use, assumes SL Mesonet Webservices. | |
* @param {object} apiParameters - Any valid parameter for the specified SL Mesonet Webservice. | |
*/ | |
function worker(baseURL, apiParameters) { | |
// Fetch data from the Mesonet API. | |
getData(baseURL, apiParameters) | |
.then((data) => { | |
// If successful then create the list items to append to the 'ticker' | |
// console.log(data) | |
addEntryToMarquee(data); | |
}).catch((error) => { | |
console.error('Unexepected error has occured\n', error); | |
}) | |
} | |
function addEntryToMarquee(data) { | |
let $container = document.getElementById('app-container'); | |
let $scrollItems = document.createElement('DIV'); | |
$scrollItems.classList.add('ticker'); | |
$scrollItems.id = '__scroll-items'; | |
data.STATION.map((k) => { | |
let $item = document.createElement('DIV'); | |
$item.innerHTML = `${k.STID} Air Temp: ${k.OBSERVATIONS.air_temp_value_1.value} <sup>°</sup>F`; | |
$item.classList.add('ticker-item'); | |
$scrollItems.appendChild($item); | |
}) | |
$container.appendChild($scrollItems); | |
} | |
function removeElementById(id) { | |
if (document.getElementById(id)) { | |
let el = document.getElementById(id); | |
return el.parentNode.removeChild(el); | |
} else { | |
return null; | |
} | |
} | |
function serializeURLArgs(obj) { | |
let str = ['?']; | |
for (let p in obj) { | |
if (obj.hasOwnProperty(p)) { str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p])); } | |
} | |
return str.join('&'); | |
} | |
function getData(baseURL = '', args = {}) { | |
return new Promise((resolve, reject) => { | |
state.api.requestURL = state.api.apiBaseURL + baseURL + serializeURLArgs(args); | |
fetch(state.api.requestURL) | |
.then((response) => { return response.json(); }) | |
.then((data) => { | |
store.data = data; | |
state.haveData = true; | |
resolve(data); | |
}) | |
.catch((error) => reject(error)); | |
}); | |
} | |
}()); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment