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