Use flex-based layout to reduce visual waste

This commit is contained in:
Florine W. Dekker 2022-11-23 13:47:48 +01:00
parent afcbf7f94e
commit 7789363797
Signed by: FWDekker
GPG Key ID: D3DCFAA8A4560BE0
6 changed files with 76 additions and 50 deletions

View File

@ -7,18 +7,21 @@ module.exports = grunt => {
default: ["dist/"],
},
copy: {
css: {
files: [{expand: true, cwd: "src/main/", src: "**/*.css", dest: "dist/", flatten: true}],
},
html: {
files: [{expand: true, cwd: "src/main/", src: "**/*.html", dest: "dist/", flatten: true}]
files: [{expand: true, cwd: "src/main/", src: "**/*.html", dest: "dist/", flatten: true}],
},
},
focus: {
dev: {
include: ["html", "js"],
include: ["css", "html", "js"],
},
},
replace: {
dev: {
src: ["./dist/*.html", "./dist/*.js"],
src: ["./dist/**/*.html", "./dist/**/*.js"],
replacements: [
{
from: "%%VERSION_NUMBER%%",
@ -28,7 +31,7 @@ module.exports = grunt => {
overwrite: true
},
deploy: {
src: ["./dist/*.html", "./dist/*.js"],
src: ["./dist/**/*.html", "./dist/**/*.js"],
replacements: [
{
from: "%%VERSION_NUMBER%%",
@ -39,6 +42,10 @@ module.exports = grunt => {
},
},
watch: {
css: {
files: ["src/main/**/*.css"],
tasks: ["copy:css"],
},
html: {
files: ["src/main/**/*.html"],
tasks: ["copy:html"],
@ -88,6 +95,7 @@ module.exports = grunt => {
// Pre
"clean",
// Copy files
"copy:css",
"copy:html",
// Compile JS
"webpack:dev",
@ -98,6 +106,7 @@ module.exports = grunt => {
// Pre
"clean",
// Copy files
"copy:css",
"copy:html",
// Compile JS
"webpack:deploy",

BIN
package-lock.json generated

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"name": "converter",
"version": "1.4.14",
"version": "1.5.0",
"description": "Convert numbers to and from various bases.",
"author": "Florine W. Dekker",
"browser": "dist/bundle.js",

16
src/main/css/main.css Normal file
View File

@ -0,0 +1,16 @@
#inputs {
display: flex;
flex-wrap: wrap;
align-items: start;
justify-content: left;
/*noinspection CssUnresolvedCustomProperty*/
gap: var(--spacing);
}
#inputs article {
margin: 0;
}
#inputs textarea {
display: block;
}

View File

@ -8,6 +8,7 @@
<meta name="description" content="Convert numbers to and from various bases." />
<meta name="theme-color" content="#0033cc" />
<meta name="fwd:auto:show-main" />
<meta name="fwd:nav:target" content="#nav" />
<meta name="fwd:nav:highlight-path" content="/Tools/Converter/" />
<meta name="fwd:footer:target" content="#footer" />
@ -17,6 +18,8 @@
<title>Converter | FWDekker</title>
<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>
@ -31,19 +34,24 @@
</p>
</noscript>
<nav id="nav"></nav>
<main class="container hidden">
<main class="hidden">
<div role="document">
<section>
<section class="container">
<header class="fwd-header">
<hgroup>
<h1><a href=".">Converter</a></h1>
<h2>Convert numbers to and from various bases.</h2>
</hgroup>
</header>
<form id="inputs"></form>
</section>
<section class="container-fluid">
<form id="inputs" class="grid"></form>
</section>
<section class="container">
<footer id="footer"></footer>
</section>
</div>
</main>

View File

@ -1,5 +1,5 @@
// noinspection JSUnresolvedVariable
const {$, doAfterLoad} = window.fwdekker;
const {$, doAfterLoad, stringToHtml} = window.fwdekker;
import bigInt from "big-integer"
@ -11,8 +11,9 @@ import bigInt from "big-integer"
* @param replacement the replacement to insert into the string
* @returns {string} the input string with one character replaced
*/
const stringReplaceAt = (str, index, replacement) =>
str.substring(0, index) + replacement + str.substring(index + replacement.length);
function stringReplaceAt(str, index, replacement) {
return str.substring(0, index) + replacement + str.substring(index + replacement.length);
}
/**
* Replaces all instances of the target with the replacement.
@ -22,8 +23,9 @@ const stringReplaceAt = (str, index, replacement) =>
* @param replacement the replacement to insert into the string
* @returns {string} the input string with all instances of the target replaced
*/
const stringReplaceAll = (str, target, replacement) =>
str.split(target).join(replacement);
function stringReplaceAll(str, target, replacement) {
return str.split(target).join(replacement);
}
/**
* Runs `stringReplaceAll` for each character in `targets` and `replacements`.
@ -34,9 +36,10 @@ const stringReplaceAll = (str, target, replacement) =>
* in the targets string
* @returns {string} the input string with all instances of the targets replaced
*/
const stringReplaceAlls = (str, targets, replacements) =>
Array.from(targets).reduce((output, target, index) =>
stringReplaceAll(output, target, replacements[index]), str);
function stringReplaceAlls(str, targets, replacements) {
return Array.from(targets)
.reduce((output, target, index) => stringReplaceAll(output, target, replacements[index]), str);
}
class NumeralSystem {
@ -71,26 +74,25 @@ class NumeralSystemInput {
this.name = name;
this.numeralSystem = numeralSystem;
this.label = document.createElement("label");
this.label.setAttribute("for", `${this.name}Input`);
this.label.innerHTML = this.name;
this.label = stringToHtml(`<label for="${this.name}-input">${this.name}</label>`);
this.textarea = document.createElement("textarea");
this.textarea.id = `${this.name}Input`;
this.textarea.className = "numberInput";
this.textarea = stringToHtml(`<textarea id="${this.name}-input" class="number-input"></textarea>`);
this.textarea.oninput = () => {
if (this.textarea.value === undefined || this.textarea.value === null || this.textarea.value === "")
if (this.textarea.value == null || this.textarea.value === "")
return;
this.textarea.value = this.numeralSystem.filterBaseString(this.textarea.value);
updateAllInputs(this, this.numeralSystem.baseToDecimal(this.textarea.value));
};
this.wrapper = document.createElement("article");
this.wrapper.appendChild(this.label);
this.wrapper.appendChild(this.textarea);
}
addToParent(parent) {
parent.appendChild(this.label);
parent.appendChild(this.textarea);
parent.appendChild(this.wrapper);
}
update(decimalNumber) {
@ -98,6 +100,7 @@ class NumeralSystemInput {
}
}
class Base64NumeralSystem extends NumeralSystem {
// TODO Convert static methods to static properties once supported by Firefox
static defaultAlphabet() {
@ -148,20 +151,21 @@ class Base64NumeralSystemInput extends NumeralSystemInput {
constructor(name) {
super(name, new Base64NumeralSystem(Base64NumeralSystem.defaultAlphabet()));
this.dropdown = document.createElement("select");
this.dropdown.id = `${this.name}-dropdown`;
this.dropdown = stringToHtml(`<select id="${this.name}-dropdown"></select>`);
this.dropdown.onchange = () => {
const selectedOption = Base64NumeralSystemInput.dropdownOptions()[this.dropdown.value];
this.setLastDigits(selectedOption[0], selectedOption[1]);
};
this.options =
Object.keys(Base64NumeralSystemInput.dropdownOptions()).map(key => {
const option = document.createElement("option");
option.value = key;
option.text = key + ": " + Base64NumeralSystemInput.dropdownOptions()[key].join("");
return option;
Object
.keys(Base64NumeralSystemInput.dropdownOptions())
.forEach(key => {
const text = key + ": " + Base64NumeralSystemInput.dropdownOptions()[key].join("");
const option = stringToHtml(`<option value="${key}">${text}</option>`);
this.dropdown.appendChild(option);
});
this.wrapper.appendChild(this.dropdown);
}
@ -174,14 +178,6 @@ class Base64NumeralSystemInput extends NumeralSystemInput {
this.textarea.value =
stringReplaceAll(stringReplaceAll(this.textarea.value, oc62, c62), oc63, c63);
}
addToParent(parent) {
this.options.forEach(option => this.dropdown.appendChild(option));
parent.appendChild(this.label);
parent.appendChild(this.dropdown);
parent.appendChild(this.textarea);
}
}
@ -202,21 +198,18 @@ const inputs = [
),
];
const updateAllInputs = (source, newValue) => {
function updateAllInputs(source, newValue) {
for (const input of inputs)
if (input !== source)
input.update(newValue);
};
}
doAfterLoad(() => {
const inputParent = $("#inputs");
const form = $("#inputs");
for (const input of inputs)
input.addToParent(inputParent);
input.addToParent(form);
updateAllInputs(undefined, bigInt(42));
inputs[0].textarea.focus();
$("main").classList.remove("hidden");
});