Upgrade to template v3
This commit is contained in:
parent
a5f3a8793d
commit
e7a5f64f60
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "doomsday",
|
||||
"version": "1.4.5",
|
||||
"version": "1.5.0",
|
||||
"description": "Test your mastery of Conway's Doomsday rule.",
|
||||
"author": "Florine W. Dekker",
|
||||
"browser": "dist/bundle.js",
|
||||
|
|
|
@ -1,54 +1,23 @@
|
|||
:root {
|
||||
--error-color: red;
|
||||
--success-color: green;
|
||||
input, button {
|
||||
width: unset;
|
||||
}
|
||||
|
||||
|
||||
/* Very unwide page */
|
||||
#inputs {
|
||||
max-width: 40rem;
|
||||
.inputs {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.quiz-input {
|
||||
max-width: 15rem;
|
||||
.inputs input {
|
||||
flex: 1;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
|
||||
/* Common elements */
|
||||
details * {
|
||||
box-sizing: border-box;
|
||||
details[open] summary,
|
||||
details summary:focus {
|
||||
/*noinspection CssUnresolvedCustomProperty*/
|
||||
color: var(--accordion-close-summary-color) !important;
|
||||
}
|
||||
|
||||
label, summary b {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
/* Input validation */
|
||||
.success-message {
|
||||
color: var(--success-color);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
.success-box {
|
||||
background-color: var(--success-color);
|
||||
border-color: var(--success-color);
|
||||
}
|
||||
|
||||
.error-box {
|
||||
background-color: var(--error-color);
|
||||
border-color: var(--error-color);
|
||||
}
|
||||
|
||||
input[data-entered=true]:valid {
|
||||
border-color: var(--success-color);
|
||||
color: var(--success-color);
|
||||
}
|
||||
|
||||
input[data-entered=true]:invalid {
|
||||
border-color: var(--error-color);
|
||||
color: var(--error-color);
|
||||
details:not([open]) summary:not(:focus) {
|
||||
/*noinspection CssUnresolvedCustomProperty*/
|
||||
color: var(--accordion-open-summary-color) !important;
|
||||
}
|
||||
|
|
|
@ -8,17 +8,23 @@
|
|||
<meta name="description" content="Test your mastery of Conway's Doomsday rule." />
|
||||
<meta name="theme-color" content="#0033cc" />
|
||||
|
||||
<meta name="fwd:nav:target" content="#nav" />
|
||||
<meta name="fwd:nav:highlight-path" content="/Tools/Doomsday/" />
|
||||
<meta name="fwd:footer:target" content="#footer" />
|
||||
<meta name="fwd:footer:vcs-url" content="https://git.fwdekker.com/tools/doomsday/" />
|
||||
<meta name="fwd:footer:version" content="v%%VERSION_NUMBER%%" />
|
||||
<meta name="fwd:validation:load-forms" />
|
||||
|
||||
<title>Doomsday | FWDekker</title>
|
||||
|
||||
<link rel="stylesheet" href="https://static.fwdekker.com/fonts/roboto/roboto.css" />
|
||||
<link rel="stylesheet" href="https://static.fwdekker.com/lib/template/2.x.x/template.css?v=%%VERSION_NUMBER%%" />
|
||||
<link rel="stylesheet" href="https://static.fwdekker.com/lib/template/3.x.x/template.css?v=%%VERSION_NUMBER%%" />
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<link rel="stylesheet" href="main.css?v=%%VERSION_NUMBER%%" />
|
||||
<script async src="https://stats.fwdekker.com/count.js"
|
||||
data-goatcounter="https://stats.fwdekker.com/count"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<noscript class="fwd-js-notice">
|
||||
<img src="https://stats.fwdekker.com/count?p=/tools/doomsday/" alt="Counting pixel" />
|
||||
|
||||
<p>
|
||||
|
@ -27,67 +33,58 @@
|
|||
instructions on how to enable JavaScript in your web browser</a>.
|
||||
</p>
|
||||
</noscript>
|
||||
<main class="hidden">
|
||||
<div id="nav"></div>
|
||||
<div id="contents">
|
||||
<div id="header"></div>
|
||||
<nav id="nav"></nav>
|
||||
<main class="hidden container">
|
||||
<div role="document">
|
||||
<section>
|
||||
<header class="fwd-header">
|
||||
<hgroup>
|
||||
<h1><a href=".">Doomsday</a></h1>
|
||||
<h2>
|
||||
Test your mastery of
|
||||
<a href="https://en.wikipedia.org/wiki/Doomsday_rule" target="_blank">Conway's Doomsday rule</a>.
|
||||
</h2>
|
||||
</hgroup>
|
||||
</header>
|
||||
</section>
|
||||
|
||||
<!-- Input -->
|
||||
<section id="inputs" class="container">
|
||||
<section>
|
||||
<form>
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<details open id="century-details">
|
||||
<summary><b id="century-title-label">Century</b></summary>
|
||||
<div class="inputWithButton">
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<input type="text" id="century-input" class="quiz-input" autocomplete="off" autofocus />
|
||||
<button type="button" id="century-submit" class="quiz-button">Check</button>
|
||||
</div>
|
||||
</details>
|
||||
<details open id="century-details">
|
||||
<summary><b id="century-title-label" data-label-for="century-input">Century</b></summary>
|
||||
<div class="inputs">
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<input type="text" id="century-input" class="quiz-input" autocomplete="off" autofocus />
|
||||
<button type="button" id="century-submit" class="quiz-button">Check</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<details open id="year-details">
|
||||
<summary><b id="year-title-label">Year</b></summary>
|
||||
<div class="inputWithButton">
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<input type="text" id="year-input" class="quiz-input" autocomplete="off" />
|
||||
<button type="button" id="year-submit" class="quiz-button">Check</button>
|
||||
</div>
|
||||
</details>
|
||||
<details open id="year-details">
|
||||
<summary><b id="year-title-label" data-label-for="year-input">Year</b></summary>
|
||||
<div class="inputs">
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<input type="text" id="year-input" class="quiz-input" autocomplete="off" />
|
||||
<button type="button" id="year-submit" class="quiz-button">Check</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<div>
|
||||
<label for="day-input" id="day-title-label">Day</label>
|
||||
<div class="inputWithButton">
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<input type="text" id="day-input" class="quiz-input" autocomplete="off" />
|
||||
<button type="button" id="day-submit" class="quiz-button">Check</button>
|
||||
</div>
|
||||
</div>
|
||||
<details open id="day-details">
|
||||
<summary><b id="day-title-label" data-label-for="day-input">Day</b></summary>
|
||||
<div class="inputs">
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<input type="text" id="day-input" class="quiz-input" autocomplete="off" />
|
||||
<button type="button" id="day-submit" class="quiz-button">Check</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="row">​</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<button type="button" id="reset-button">Reset</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" id="reset-button">Reset</button>
|
||||
</form>
|
||||
</section>
|
||||
<footer id="footer"></footer>
|
||||
</div>
|
||||
<div id="footer"></div>
|
||||
</main>
|
||||
|
||||
<script src="https://static.fwdekker.com/lib/template/2.x.x/template.js?v=%%VERSION_NUMBER%%"></script>
|
||||
<script src="https://static.fwdekker.com/lib/template/3.x.x/template.js?v=%%VERSION_NUMBER%%"></script>
|
||||
<!--suppress HtmlUnknownTarget -->
|
||||
<script src="bundle.js?v=%%VERSION_NUMBER%%"></script>
|
||||
</body>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// @ts-ignore
|
||||
const {$, doAfterLoad, footer, header, nav} = window.fwdekker;
|
||||
const {$, doAfterLoad} = window.fwdekker;
|
||||
// @ts-ignore
|
||||
const {clearInputValidity, showInputInvalid, showInputValid} = window.fwdekker.validation;
|
||||
|
||||
import {DateTime} from "luxon";
|
||||
|
||||
|
@ -62,8 +64,6 @@ class ValidatableInput {
|
|||
* Handles the user submitting the input.
|
||||
*/
|
||||
onSubmit(): void {
|
||||
this.input.dataset["entered"] = "true";
|
||||
|
||||
if (this.isValid(this.input.value)) {
|
||||
this.showSuccess();
|
||||
this.onValidInput();
|
||||
|
@ -110,39 +110,25 @@ class ValidatableInput {
|
|||
*/
|
||||
reset(): void {
|
||||
this.input.value = "";
|
||||
this.input.dataset["entered"] = "false";
|
||||
|
||||
this.showSuccess();
|
||||
this.updateTitle();
|
||||
|
||||
this.titleLabel.classList.remove("success-message");
|
||||
this.button.classList.remove("success-box");
|
||||
clearInputValidity(this.input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the input as invalid.
|
||||
*/
|
||||
showError(): void {
|
||||
this.input.setCustomValidity("Incorrect");
|
||||
|
||||
this.titleLabel.classList.remove("success-message");
|
||||
this.titleLabel.classList.add("error-message");
|
||||
|
||||
this.button.classList.remove("success-box");
|
||||
this.button.classList.add("error-box");
|
||||
showInputInvalid(this.input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the input as valid.
|
||||
*/
|
||||
showSuccess(): void {
|
||||
this.input.setCustomValidity("");
|
||||
|
||||
this.titleLabel.classList.remove("error-message");
|
||||
this.titleLabel.classList.add("success-message");
|
||||
|
||||
this.button.classList.remove("error-box");
|
||||
this.button.classList.add("success-box");
|
||||
showInputValid(this.input);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -351,19 +337,6 @@ class DoomsdayDate {
|
|||
|
||||
|
||||
doAfterLoad(() => {
|
||||
// Initialize template
|
||||
$("#nav").appendChild(nav("/Tools/Doomsday/"));
|
||||
$("#header").appendChild(header({
|
||||
title: "Doomsday",
|
||||
description: `
|
||||
Test your mastery of \
|
||||
<a href="https://en.wikipedia.org/wiki/Doomsday_rule">⎋ Conway's Doomsday rule</a>
|
||||
`
|
||||
}));
|
||||
$("#footer").appendChild(footer({
|
||||
vcsURL: "https://git.fwdekker.com/tools/doomsday/",
|
||||
version: "v%%VERSION_NUMBER%%"
|
||||
}));
|
||||
$("main").classList.remove("hidden");
|
||||
|
||||
|
||||
|
@ -384,6 +357,13 @@ doAfterLoad(() => {
|
|||
yearInput.updateTitle();
|
||||
}
|
||||
}("year", $("#year-details"));
|
||||
const dayDetails = new class extends ToggleableSection {
|
||||
onToggle(isOpened: boolean): void {
|
||||
super.onToggle(isOpened);
|
||||
if (isOpened) dayInput.selectInput();
|
||||
dayInput.updateTitle();
|
||||
}
|
||||
}("day", $("#day-details"));
|
||||
|
||||
const centuryInput = new class extends ValidatableInput {
|
||||
isValid(value: string): boolean {
|
||||
|
@ -398,8 +378,10 @@ doAfterLoad(() => {
|
|||
this.input.value = DoomsdayDate.expandDayString(this.input.value);
|
||||
if (yearDetails.isOpened())
|
||||
yearInput.selectInput();
|
||||
else
|
||||
else if (dayDetails.isOpened())
|
||||
dayInput.selectInput();
|
||||
else
|
||||
resetButton.focus();
|
||||
}
|
||||
|
||||
onInvalidInput() {
|
||||
|
@ -424,7 +406,10 @@ doAfterLoad(() => {
|
|||
|
||||
onValidInput() {
|
||||
this.input.value = DoomsdayDate.expandDayString(this.input.value);
|
||||
dayInput.selectInput();
|
||||
if (dayDetails.isOpened())
|
||||
dayInput.selectInput();
|
||||
else
|
||||
resetButton.focus();
|
||||
}
|
||||
|
||||
onInvalidInput() {
|
||||
|
@ -457,7 +442,10 @@ doAfterLoad(() => {
|
|||
}
|
||||
|
||||
updateTitle() {
|
||||
this.titleLabel.innerText = `Weekday of ${quizDate.date.toISODate()}?`;
|
||||
if (dayDetails.isOpened())
|
||||
this.titleLabel.innerText = `Weekday of ${quizDate.date.toISODate()}?`;
|
||||
else
|
||||
this.titleLabel.innerText = `Day`;
|
||||
}
|
||||
}($("#day-input"), $("#day-title-label"), $("#day-submit"));
|
||||
|
||||
|
@ -489,8 +477,10 @@ doAfterLoad(() => {
|
|||
centuryInput.selectInput();
|
||||
else if (yearDetails.isOpened())
|
||||
yearInput.selectInput();
|
||||
else
|
||||
else {
|
||||
dayDetails.setOpened(true);
|
||||
dayInput.selectInput();
|
||||
}
|
||||
}
|
||||
|
||||
// Let the fun begin
|
||||
|
|
Loading…
Reference in New Issue