Skip to content

Instantly share code, notes, and snippets.

@WebReflection
Last active December 16, 2019 08:15
Show Gist options
  • Save WebReflection/c4b802bc61578e85436f6e58e61d2789 to your computer and use it in GitHub Desktop.
Save WebReflection/c4b802bc61578e85436f6e58e61d2789 to your computer and use it in GitHub Desktop.
A basic hyperHTML + Firebase example. 100% client side.
<!doctype html>
<html lang="en">
<head>
<title>hyperHTML &amp; 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>
@WebReflection
Copy link
Author

@albertosantini
Copy link

albertosantini commented Sep 10, 2017

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