JSFiddle - React, Tailwind, and code Playground
by mepcott
HTML
<section id="searchArea">
<header>
<form>
<label for="breeds">Breeds:</label>
<select name="breed" id="breedList" disabled>
<!-- populate with fetch -->
</select>
<input id="fetchImagesButton" type="button" value="Fetch Images" disabled>
</form>
</header>
<div id="imageList">
<!-- populate with fetch -->
</div>
<footer>
<small>
Powered by the
<a href="https://dog.ceo/dog-api/">Dog API</a>.
</small>
</footer>
</section>
CSS
#searchArea {
font-family: sans-serif;
display: flex;
flex-flow: column nowrap;
align-items: center;
gap: 1em;
}
#searchArea > header > form {
display: flex;
justify-content: center;
align-items: center;
gap: 0.25rem;
}
#searchArea > #imageList > img {
width: 64px;
height: 64px;
}
JavaScript
class RestApi {
constructor(endpoint) {
this.endpoint = endpoint;
} // constructor
okOrThrow(response) {
if (response.ok) {
return response;
} else {
throw new Error(`HTTP ${response.status}`)
} // if
} // check
fetch(...args) {
let method = args.join("/");
return fetch(this.endpoint + method)
.then(this.okOrThrow)
} // fetch
} // RestApi
const dogApi = new RestApi("https://dog.ceo/api/");
const breedList = document.querySelector("#breedList");
const imageList = document.querySelector("#imageList");
const fetchImagesButton = document.querySelector("#fetchImagesButton");
function option(value, text) {
element = document.createElement("option");
element.value = value;
element.textContent = text;
return element;
} // option
function image(src, alt) {
element = document.createElement("img");
element.src = src;
element.alt = alt;
return element;
} // image
function initBreeds(breeds) {
if (breeds.length > 0) {
breeds.forEach(breed => breedList.appendChild(option(breed, breed)));
breedList.disabled = false;
fetchImagesButton.disabled = false;
} // if
} // initBreeds
function updateImages(urls) {
if (urls.length > 0) {
imageList.innerHTML = "";
urls.forEach(url => imageList.appendChild(image(url)));
} else {
imageList.innerHTML = "No results...";
} // if
fetchImagesButton.disabled = false;
} // updateImages
function fetchImages() {
let name = breedList.options[breedList.selectedIndex].textContent;
imageList.innerHTML = "Loading...";
fetchImagesButton.disabled = true;
dogApi.fetch("breed", name, "images")
.then(response => response.json())
.then(data => data.message)
.then(urls => updateImages(urls));
} // fetchImages
dogApi.fetch("breeds", "list", "all")
.then(response => response.json())
.then(data => Object.keys(data.message))
.then(breeds => initBreeds(breeds))
fetchImagesButton.addEventListener("click", fetchImages, false);