<h1 class="page-title">CATS 🐈</h1>
<img src="https://cataas.com/cat?width=400&height=300" alt="" height="300" width="400" />
<button type="button" class="js-new-cat new-cat-button">New cat!</button>
<footer>Big thanks to <a href="https://cataas.com">Cat as a service</a></footer>
*,
*::before,
*::after {
box-sizing: border-box;
}
* {
margin-bottom: 0;
}
* + * {
margin-top: 2rem;
}
:focus {
outline: 0.25rem solid tomato;
outline-offset: 0.2rem;
}
button,
input,
textarea {
font-family: inherit;
font-size: inherit;
}
:root {
font-size: calc(1rem + 0.5vw);
}
body {
align-items: center;
background-color: paleturquoise;
display: flex;
flex-direction: column;
font-family: monospace;
justify-content: center;
margin: 0;
min-height: 100vh;
padding: 0 0 4rem;
}
.page-title {
background-color: white;
font-size: 2rem;
font-style: italic;
padding: 0.25em;
text-align: center;
}
.new-cat-button,
.confirm-dialog-button {
background-color: white;
border: 0.35em solid;
border-bottom-color: steelblue;
border-left-color: cadetblue;
border-right-color: steelblue;
border-top-color: cadetblue;
cursor: pointer;
font-size: 1.25rem;
padding: 0.75em 1em;
}
img {
border-radius: 0.75rem;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
max-width: 100%;
object-fit: cover;
}
.confirm-dialog {
max-width: 45em;
padding: 2rem;
width: 90vw;
&::backdrop {
background-color: rgba(0, 0, 0, 0.3);
}
}
.confirm-dialog-question {
font-size: 1.5em;
font-style: italic;
font-weight: 600;
}
.confirm-dialog-button-group {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
margin: 1rem -1rem -1rem;
> * {
margin: 1rem;
}
}
.confirm-dialog-button {
font-size: 1rem;
}
footer {
margin-top: 5rem;
padding: 0 1rem;
}
View Compiled
const image = document.querySelector("img");
const newCatButton = document.querySelector(".js-new-cat");
newCatButton.addEventListener("click", async () => {
const dialog = new ConfirmDialog({
trueButtonText: "Yes!",
falseButtonText: "Noo",
questionText: "Are you sure you want to see yet another picture of a cat?"
});
const shouldFetchNewImage = await dialog.confirm();
if (shouldFetchNewImage) {
image.src = `https://cataas.com/cat?width=400&height=300×tamp=${Date.now()}`;
}
});
class ConfirmDialog {
constructor({ questionText, trueButtonText, falseButtonText, parent }) {
this.questionText = questionText || "Are you sure?";
this.trueButtonText = trueButtonText || "Yes";
this.falseButtonText = falseButtonText || "No";
this.parent = parent || document.body;
this.dialog = undefined;
this.trueButton = undefined;
this.falseButton = undefined;
this._createDialog();
this._appendDialog();
}
confirm() {
return new Promise((resolve, reject) => {
const somethingWentWrongUponCreation =
!this.dialog || !this.trueButton || !this.falseButton;
if (somethingWentWrongUponCreation) {
reject('Someting went wrong when creating the modal');
return;
}
this.dialog.showModal();
this.trueButton.focus();
this.trueButton.addEventListener("click", () => {
resolve(true);
this._destroy();
});
this.falseButton.addEventListener("click", () => {
resolve(false);
this._destroy();
});
});
}
_createDialog() {
this.dialog = document.createElement("dialog");
this.dialog.classList.add("confirm-dialog");
const question = document.createElement("div");
question.textContent = this.questionText;
question.classList.add("confirm-dialog-question");
this.dialog.appendChild(question);
const buttonGroup = document.createElement("div");
buttonGroup.classList.add("confirm-dialog-button-group");
this.dialog.appendChild(buttonGroup);
this.falseButton = document.createElement("button");
this.falseButton.classList.add(
"confirm-dialog-button",
"confirm-dialog-button--false"
);
this.falseButton.type = "button";
this.falseButton.textContent = this.falseButtonText;
buttonGroup.appendChild(this.falseButton);
this.trueButton = document.createElement("button");
this.trueButton.classList.add(
"confirm-dialog-button",
"confirm-dialog-button--true"
);
this.trueButton.type = "button";
this.trueButton.textContent = this.trueButtonText;
buttonGroup.appendChild(this.trueButton);
}
_appendDialog() {
this.parent.appendChild(this.dialog);
}
_destroy() {
this.parent.removeChild(this.dialog);
delete this;
}
}
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.