Use flex-based layout to reduce visual waste
This commit is contained in:
parent
afcbf7f94e
commit
7789363797
17
Gruntfile.js
17
Gruntfile.js
|
@ -7,18 +7,21 @@ module.exports = grunt => {
|
||||||
default: ["dist/"],
|
default: ["dist/"],
|
||||||
},
|
},
|
||||||
copy: {
|
copy: {
|
||||||
|
css: {
|
||||||
|
files: [{expand: true, cwd: "src/main/", src: "**/*.css", dest: "dist/", flatten: true}],
|
||||||
|
},
|
||||||
html: {
|
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: {
|
focus: {
|
||||||
dev: {
|
dev: {
|
||||||
include: ["html", "js"],
|
include: ["css", "html", "js"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
replace: {
|
replace: {
|
||||||
dev: {
|
dev: {
|
||||||
src: ["./dist/*.html", "./dist/*.js"],
|
src: ["./dist/**/*.html", "./dist/**/*.js"],
|
||||||
replacements: [
|
replacements: [
|
||||||
{
|
{
|
||||||
from: "%%VERSION_NUMBER%%",
|
from: "%%VERSION_NUMBER%%",
|
||||||
|
@ -28,7 +31,7 @@ module.exports = grunt => {
|
||||||
overwrite: true
|
overwrite: true
|
||||||
},
|
},
|
||||||
deploy: {
|
deploy: {
|
||||||
src: ["./dist/*.html", "./dist/*.js"],
|
src: ["./dist/**/*.html", "./dist/**/*.js"],
|
||||||
replacements: [
|
replacements: [
|
||||||
{
|
{
|
||||||
from: "%%VERSION_NUMBER%%",
|
from: "%%VERSION_NUMBER%%",
|
||||||
|
@ -39,6 +42,10 @@ module.exports = grunt => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
css: {
|
||||||
|
files: ["src/main/**/*.css"],
|
||||||
|
tasks: ["copy:css"],
|
||||||
|
},
|
||||||
html: {
|
html: {
|
||||||
files: ["src/main/**/*.html"],
|
files: ["src/main/**/*.html"],
|
||||||
tasks: ["copy:html"],
|
tasks: ["copy:html"],
|
||||||
|
@ -88,6 +95,7 @@ module.exports = grunt => {
|
||||||
// Pre
|
// Pre
|
||||||
"clean",
|
"clean",
|
||||||
// Copy files
|
// Copy files
|
||||||
|
"copy:css",
|
||||||
"copy:html",
|
"copy:html",
|
||||||
// Compile JS
|
// Compile JS
|
||||||
"webpack:dev",
|
"webpack:dev",
|
||||||
|
@ -98,6 +106,7 @@ module.exports = grunt => {
|
||||||
// Pre
|
// Pre
|
||||||
"clean",
|
"clean",
|
||||||
// Copy files
|
// Copy files
|
||||||
|
"copy:css",
|
||||||
"copy:html",
|
"copy:html",
|
||||||
// Compile JS
|
// Compile JS
|
||||||
"webpack:deploy",
|
"webpack:deploy",
|
||||||
|
|
Binary file not shown.
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "converter",
|
"name": "converter",
|
||||||
"version": "1.4.14",
|
"version": "1.5.0",
|
||||||
"description": "Convert numbers to and from various bases.",
|
"description": "Convert numbers to and from various bases.",
|
||||||
"author": "Florine W. Dekker",
|
"author": "Florine W. Dekker",
|
||||||
"browser": "dist/bundle.js",
|
"browser": "dist/bundle.js",
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
<meta name="description" content="Convert numbers to and from various bases." />
|
<meta name="description" content="Convert numbers to and from various bases." />
|
||||||
<meta name="theme-color" content="#0033cc" />
|
<meta name="theme-color" content="#0033cc" />
|
||||||
|
|
||||||
|
<meta name="fwd:auto:show-main" />
|
||||||
<meta name="fwd:nav:target" content="#nav" />
|
<meta name="fwd:nav:target" content="#nav" />
|
||||||
<meta name="fwd:nav:highlight-path" content="/Tools/Converter/" />
|
<meta name="fwd:nav:highlight-path" content="/Tools/Converter/" />
|
||||||
<meta name="fwd:footer:target" content="#footer" />
|
<meta name="fwd:footer:target" content="#footer" />
|
||||||
|
@ -17,6 +18,8 @@
|
||||||
<title>Converter | FWDekker</title>
|
<title>Converter | FWDekker</title>
|
||||||
|
|
||||||
<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/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"
|
<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>
|
||||||
|
@ -31,19 +34,24 @@
|
||||||
</p>
|
</p>
|
||||||
</noscript>
|
</noscript>
|
||||||
<nav id="nav"></nav>
|
<nav id="nav"></nav>
|
||||||
<main class="container hidden">
|
<main class="hidden">
|
||||||
<div role="document">
|
<div role="document">
|
||||||
<section>
|
<section class="container">
|
||||||
<header class="fwd-header">
|
<header class="fwd-header">
|
||||||
<hgroup>
|
<hgroup>
|
||||||
<h1><a href=".">Converter</a></h1>
|
<h1><a href=".">Converter</a></h1>
|
||||||
<h2>Convert numbers to and from various bases.</h2>
|
<h2>Convert numbers to and from various bases.</h2>
|
||||||
</hgroup>
|
</hgroup>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form id="inputs"></form>
|
|
||||||
</section>
|
</section>
|
||||||
<footer id="footer"></footer>
|
|
||||||
|
<section class="container-fluid">
|
||||||
|
<form id="inputs" class="grid"></form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="container">
|
||||||
|
<footer id="footer"></footer>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// noinspection JSUnresolvedVariable
|
// noinspection JSUnresolvedVariable
|
||||||
const {$, doAfterLoad} = window.fwdekker;
|
const {$, doAfterLoad, stringToHtml} = window.fwdekker;
|
||||||
import bigInt from "big-integer"
|
import bigInt from "big-integer"
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,8 +11,9 @@ import bigInt from "big-integer"
|
||||||
* @param replacement the replacement to insert into the string
|
* @param replacement the replacement to insert into the string
|
||||||
* @returns {string} the input string with one character replaced
|
* @returns {string} the input string with one character replaced
|
||||||
*/
|
*/
|
||||||
const stringReplaceAt = (str, index, replacement) =>
|
function stringReplaceAt(str, index, replacement) {
|
||||||
str.substring(0, index) + replacement + str.substring(index + replacement.length);
|
return str.substring(0, index) + replacement + str.substring(index + replacement.length);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces all instances of the target with the replacement.
|
* 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
|
* @param replacement the replacement to insert into the string
|
||||||
* @returns {string} the input string with all instances of the target replaced
|
* @returns {string} the input string with all instances of the target replaced
|
||||||
*/
|
*/
|
||||||
const stringReplaceAll = (str, target, replacement) =>
|
function stringReplaceAll(str, target, replacement) {
|
||||||
str.split(target).join(replacement);
|
return str.split(target).join(replacement);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs `stringReplaceAll` for each character in `targets` and `replacements`.
|
* Runs `stringReplaceAll` for each character in `targets` and `replacements`.
|
||||||
|
@ -34,9 +36,10 @@ const stringReplaceAll = (str, target, replacement) =>
|
||||||
* in the targets string
|
* in the targets string
|
||||||
* @returns {string} the input string with all instances of the targets replaced
|
* @returns {string} the input string with all instances of the targets replaced
|
||||||
*/
|
*/
|
||||||
const stringReplaceAlls = (str, targets, replacements) =>
|
function stringReplaceAlls(str, targets, replacements) {
|
||||||
Array.from(targets).reduce((output, target, index) =>
|
return Array.from(targets)
|
||||||
stringReplaceAll(output, target, replacements[index]), str);
|
.reduce((output, target, index) => stringReplaceAll(output, target, replacements[index]), str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class NumeralSystem {
|
class NumeralSystem {
|
||||||
|
@ -71,26 +74,25 @@ class NumeralSystemInput {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.numeralSystem = numeralSystem;
|
this.numeralSystem = numeralSystem;
|
||||||
|
|
||||||
this.label = document.createElement("label");
|
this.label = stringToHtml(`<label for="${this.name}-input">${this.name}</label>`);
|
||||||
this.label.setAttribute("for", `${this.name}Input`);
|
|
||||||
this.label.innerHTML = this.name;
|
|
||||||
|
|
||||||
this.textarea = document.createElement("textarea");
|
this.textarea = stringToHtml(`<textarea id="${this.name}-input" class="number-input"></textarea>`);
|
||||||
this.textarea.id = `${this.name}Input`;
|
|
||||||
this.textarea.className = "numberInput";
|
|
||||||
this.textarea.oninput = () => {
|
this.textarea.oninput = () => {
|
||||||
if (this.textarea.value === undefined || this.textarea.value === null || this.textarea.value === "")
|
if (this.textarea.value == null || this.textarea.value === "")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.textarea.value = this.numeralSystem.filterBaseString(this.textarea.value);
|
this.textarea.value = this.numeralSystem.filterBaseString(this.textarea.value);
|
||||||
updateAllInputs(this, this.numeralSystem.baseToDecimal(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) {
|
addToParent(parent) {
|
||||||
parent.appendChild(this.label);
|
parent.appendChild(this.wrapper);
|
||||||
parent.appendChild(this.textarea);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update(decimalNumber) {
|
update(decimalNumber) {
|
||||||
|
@ -98,6 +100,7 @@ class NumeralSystemInput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Base64NumeralSystem extends NumeralSystem {
|
class Base64NumeralSystem extends NumeralSystem {
|
||||||
// TODO Convert static methods to static properties once supported by Firefox
|
// TODO Convert static methods to static properties once supported by Firefox
|
||||||
static defaultAlphabet() {
|
static defaultAlphabet() {
|
||||||
|
@ -148,20 +151,21 @@ class Base64NumeralSystemInput extends NumeralSystemInput {
|
||||||
constructor(name) {
|
constructor(name) {
|
||||||
super(name, new Base64NumeralSystem(Base64NumeralSystem.defaultAlphabet()));
|
super(name, new Base64NumeralSystem(Base64NumeralSystem.defaultAlphabet()));
|
||||||
|
|
||||||
this.dropdown = document.createElement("select");
|
this.dropdown = stringToHtml(`<select id="${this.name}-dropdown"></select>`);
|
||||||
this.dropdown.id = `${this.name}-dropdown`;
|
|
||||||
this.dropdown.onchange = () => {
|
this.dropdown.onchange = () => {
|
||||||
const selectedOption = Base64NumeralSystemInput.dropdownOptions()[this.dropdown.value];
|
const selectedOption = Base64NumeralSystemInput.dropdownOptions()[this.dropdown.value];
|
||||||
this.setLastDigits(selectedOption[0], selectedOption[1]);
|
this.setLastDigits(selectedOption[0], selectedOption[1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.options =
|
Object
|
||||||
Object.keys(Base64NumeralSystemInput.dropdownOptions()).map(key => {
|
.keys(Base64NumeralSystemInput.dropdownOptions())
|
||||||
const option = document.createElement("option");
|
.forEach(key => {
|
||||||
option.value = key;
|
const text = key + ": " + Base64NumeralSystemInput.dropdownOptions()[key].join("");
|
||||||
option.text = key + ": " + Base64NumeralSystemInput.dropdownOptions()[key].join("");
|
const option = stringToHtml(`<option value="${key}">${text}</option>`);
|
||||||
return option;
|
this.dropdown.appendChild(option);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.wrapper.appendChild(this.dropdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -174,14 +178,6 @@ class Base64NumeralSystemInput extends NumeralSystemInput {
|
||||||
this.textarea.value =
|
this.textarea.value =
|
||||||
stringReplaceAll(stringReplaceAll(this.textarea.value, oc62, c62), oc63, c63);
|
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)
|
for (const input of inputs)
|
||||||
if (input !== source)
|
if (input !== source)
|
||||||
input.update(newValue);
|
input.update(newValue);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
doAfterLoad(() => {
|
doAfterLoad(() => {
|
||||||
const inputParent = $("#inputs");
|
const form = $("#inputs");
|
||||||
|
|
||||||
for (const input of inputs)
|
for (const input of inputs)
|
||||||
input.addToParent(inputParent);
|
input.addToParent(form);
|
||||||
|
|
||||||
updateAllInputs(undefined, bigInt(42));
|
updateAllInputs(undefined, bigInt(42));
|
||||||
inputs[0].textarea.focus();
|
inputs[0].textarea.focus();
|
||||||
|
|
||||||
$("main").classList.remove("hidden");
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue