Published
Edited
Apr 22, 2020
4 stars
Also listed in…
Experiments
Insert cell
Insert cell
{
const el = DOM.element('div');
renderer.render(
jsx`
<div class="container">
<div class=quote>
<${Greeting} name=${'You'}/>
<${Timer} />
<${Quotes} />
</div>
<div class=dog>
<${RandomDogApp}/>
</div>
</div>
`,
el
);
return el;
}
Insert cell
async function QuoteOfTheDay() {
const res = await fetch("https://favqs.com/api/qotd");
const { quote } = await res.json();
console.log(quote);
return jsx`
<p>
“<${Raw} value=${quote.body} />” – <a target="_blank" href=${quote.url}>${quote.author}</a>
</p>
`;
}
Insert cell
function* Quotes() {
const interval = setInterval(() => {
this.refresh();
}, 5000);
try {
while (true) {
yield jsx`
<${QuoteOfTheDay} />
`;
}
} finally {
clearInterval(interval);
}
invalidation.then(() => clearInterval(interval));
}
Insert cell
function Greeting({ name = "World" }) {
return jsx`
<div>Hello ${name}</div>
`;
}
Insert cell
function* Timer() {
let seconds = 0;
const interval = setInterval(() => {
seconds++;
this.refresh();
}, 1000);
try {
while (true) {
yield jsx`<div>Seconds: ${seconds}</div>`;
}
} finally {
clearInterval(interval);
}
}
Insert cell
async function* LoadingIndicator() {
await Promises.delay(1000);
return jsx`<div>Fetching a good boy...</div>`;
}
Insert cell
async function RandomDog({ throttle = false }) {
const res = await fetch("https://dog.ceo/api/breeds/image/random");
const data = await res.json();
if (throttle) {
await Promises.delay(1000);
}

return jsx`
<a target="_blank" href=${data.message}>
<img class="img-fluid" src=${data.message} alt="A Random Dog" width="300" />
</a>
`;
}
Insert cell
async function* RandomDogLoader({ throttle }) {
for await ({ throttle } of this) {
yield jsx`<${LoadingIndicator}/>`;
yield jsx`<${RandomDog} throttle=${throttle} />`;
}
}
Insert cell
function* RandomDogApp() {
let throttle = false;
this.addEventListener("click", ev => {
if (ev.target.tagName === "BUTTON") {
throttle = !throttle;
this.refresh();
}
});

while (true) {
yield jsx`
<${Fragment}>
<div>
<button>Show me another dog.</button>
</div>
<${RandomDogLoader} throttle=${throttle} />
</${Fragment}>`;
}
}
Insert cell
html`
<style>
.container {
background: #333333;
color: white;
padding: 1rem;
display: flex;
}
.container button {
font-size: 1rem;
padding: 0.5rem;
border-radius: 10px;
}
.container .quote{
padding: 0.5rem;
flex-basis: 50%;
}
.container .dog {
padding: 0.5rem;
min-height: 350px;
flex-basis: 50%;
}
.img-fluid {
width: 100%;
heigth: auto;
}

@media (max-width: 650px){
.container {
flex-wrap: wrap;
}
.container .dog {
flex-basis: 100%;
}
.container .quote{
flex-basis: 100%;
}
}
</style>
`
Insert cell
createElement = (await import('https://unpkg.com/@bikeshaving/crank@0.1.0/esm/index.js?module'))
.createElement
Insert cell
Fragment = (await import('https://unpkg.com/@bikeshaving/crank@0.1.0/esm/index.js?module'))
.Fragment
Insert cell
Raw = (await import('https://unpkg.com/@bikeshaving/crank@0.1.0/esm/index.js?module'))
.Raw
Insert cell
renderer = (await import('https://unpkg.com/@bikeshaving/crank@0.1.0/dom.js?module'))
.renderer
Insert cell
htm = require('htm@3.0.4/dist/htm.umd.js')
Insert cell
jsx = htm.bind(createElement)
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more