Last active
December 16, 2019 08:15
-
-
Save WebReflection/c4b802bc61578e85436f6e58e61d2789 to your computer and use it in GitHub Desktop.
A basic hyperHTML + Firebase example. 100% client side.
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
<!doctype html> | |
<html lang="en"> | |
<head> | |
<title>hyperHTML & Firebase</title> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width,initial-scale=1.0"> | |
<style> | |
html { font-family: sans-serif; } | |
html, body, ul, p { padding: 0; margin: 0; } | |
ul, li { list-style: none; } | |
body > p, li { padding: 8px; } | |
li:nth-child(2n + 1) { background-color: #eee; } | |
li > * { display: block; } | |
li > span:last-child { font-size: .9em; text-align: right; color: #666; } | |
li > a, li > span:first-child { font-size: 1.1em; font-weight: bold; | |
text-decoration: none; line-height: 32px; } | |
</style> | |
<!-- JS dependencies: hyperHTML and Firebase --> | |
<script src="https://unpkg.com/hyperhtml@latest/min.js"></script> | |
<script src="https://www.gstatic.com/firebasejs/4.2.0/firebase.js"></script> | |
</head> | |
<body></body> | |
<script> | |
(() => { | |
const {bind, wire} = hyperHTML; | |
// in this example, we are not going | |
// to relate any specific object to wires, | |
// so we can just use html`content` | |
const html = (...args) => wire()(...args); | |
// the Firebase DB | |
const db = firebase | |
.initializeApp({databaseURL: 'https://hacker-news.firebaseio.com'}) | |
.database() | |
.ref( 'v0' ); | |
// let's use the body as hyperHTML context to populate | |
bind(document.body) | |
`${{ | |
// show an indication that something is happening | |
placeholder: {html: '<p>Loading ...</p>'}, | |
// while downloading latest top stories | |
// and creating the list of all items | |
any: new Promise(resolve => { | |
db.child('topstories') | |
.on('value', snap => { | |
resolve( | |
// instead of "Loading ..." | |
// we want now to put a UL element | |
// and show all the received items | |
html`<ul>${mapItems(snap.val())}</ul>` | |
); | |
}); | |
}) | |
}}`; | |
function mapItems(items) { | |
// per each id we create an LI element | |
return items.map( | |
id => html`<li data-id=${id}>${loadItem(id)}</li>` | |
); | |
} | |
function loadItem(id) { | |
// per each LI we load asynchronously basic story info | |
return { | |
placeholder: `fetching ${id} ...`, | |
any: new Promise(resolve => { | |
db.child(`/item/${id}`) | |
.once('value', snap => { | |
const item = snap.val(); | |
const hostname = item.hostname || item.url; | |
resolve(html` | |
${{any: hostname ? | |
// if there is an hostname/url to show | |
// put a link and a shortened hostname info | |
html`<a href=${item.url} target=_blank>${item.title}</a> | |
<small> | |
${new URL(hostname).hostname.replace(/^www\./, '')} | |
</small>`: | |
// otherwise just show the title | |
html`<span>${item.title}</span>` | |
}} | |
<!-- show some extra info --> | |
<span>${item.score} points by <b>${item.by}</b></span>`); | |
}); | |
}) | |
}; | |
} | |
})(); | |
</script> | |
</html> |
If you are wondering, like me, about placeholder
and any
properties and how it works, you may see the async setup.
https://viperhtml.js.org/hyperhtml/documentation/#essentials-10
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Code Pen
Plnkr