Make the quote generator generically extensible & declarative

This commit is contained in:
kiril 2024-08-11 00:25:41 +00:00
parent 9168154c79
commit f4f0939cee

View File

@ -13,27 +13,59 @@
text-decoration-style: dotted;
text-decoration: underline;
}
html {
background-color: black;
filter: invert(1);
}
</style>
<script>
const basic = "basic";
const additional = "additional";
const parameters = {
"type": "Type",
"language": "Language(s)",
"text": "Text",
"t": "Translation or re-wording",
"year": "Year",
"author": "Author",
"title": "Title",
"volume": "Volume",
"translator": "Translator",
"trans-title": "Translated title",
"series": "Series",
"isbn": "ISBN"
"type": {label: "Type", section: basic, type: "dropdown", fields: {
"book": "Book",
"web": "Web",
"song": "Song",
"journal": "Journal",
"wikipedia": "Wikipedia"
}},
"language": {label: "Language(s)", section: basic},
"text": {label: "Text", section: basic, type: "textarea"},
"t": {label: "Translation or re-wording", section: basic, type: "textarea"},
"year": {label: "Year", section: basic},
"author": {label: "Author", section: basic},
"title": {label: "Title", section: basic},
"volume": {label: "Volume", section: additional},
"chapter": {label: "Chapter", section: additional},
"page": {label: "Page", section: additional},
"publisher": {label: "Publisher", section: additional},
"location": {label: "Location", section: additional},
"url": {label: "URL", section: additional},
"pageurl": {label: "Page URL", section: additional},
"original": {label: "Original title", section: additional},
"origlang": {label: "Original language", section: additional},
"origyear": {label: "Original year", section: additional},
"translator": {label: "Translator", section: additional},
"trans-title": {label: "Translated title", section: additional},
"series": {label: "Series", section: additional},
"isbn": {label: "ISBN", section: additional},
"format": {label: "Format", section: additional, type: "dropdown", fields: {
"": "(unspecified)",
"hardcover": "Hardcover",
"paperback": "Paperback",
"blog": "Blog"
}},
"genre": {label: "Genre", section: additional, type: "dropdown", fields: {
"": "(unspecified)",
"fiction": "Fiction",
"non-fiction": "Non-fiction"
}}
}
let presetMenu;
addEventListener("DOMContentLoaded", (event) => {
presetMenu = document.getElementById("presets");
presetMenu.addEventListener("change", () => loadPreset(presetMenu.value));
generatePropertyInputs();
loadPresetList();
});
</script>
@ -42,36 +74,21 @@
<h1 style="display: inline-block">en.wiktionary Quote Generator</h1> <span class="gloss" title="Enter values for each of the quote template fields. Once you're done, click Generate or Copy to clipboard to get the output as wikitext. You may set presets to skip out the repetitive bits if quoting from the same book many times.">(?)</span>
<form>
<hr>
<div id="basic">
<h2>Basic information</h2>
<hr>
<label for="type">Type</label>
<select id="type">
<option value="book">Book</option>
<option value="web">Web</option>
<option value="song">Song</option>
<option value="journal">Journal</option>
<option value="wikipedia">Wikipedia</option>
</select>
<label>Language(s)</label> <input type="text" id="language">
<label>Text</label> <input type="text" id="text">
<label>Translation or re-wording</label> <input type="text" id="t">
<label>Year</label> <input type="text" id="year">
<label>Author</label> <input type="text" id="author">
<label>Title</label> <input type="text" id="title">
</div>
<hr>
<div id="additional">
<h2>Additional information</h2>
<hr>
<br>
<label>Volume</label> <input type="text" id="volume">
<label>Translator</label> <input type="text" id="translator">
<label>Translated title</label> <input type="text" id="trans-title">
<label>Series</label> <input type="text" id="series">
<label>ISBN</label> <input type="text" id="isbn">
</div>
<br>
<input type="button" onclick="generate()" value="Generate" title="Generate">
<input type="button" onclick="copy()" value="Copy to clipboard" title="Copy to clipboard">
<br>
<textarea readonly="true" id="out" cols="40" rows="4"></textarea>
<textarea readonly="true" id="out" cols="60" rows="6"></textarea>
<hr>
<label>Preset <span class="gloss" title="When a preset name is input in the 'preset name' box below, you can save the current state of each option as a preset, which will be loaded again even if the page is refreshed.">(?)</span></label>
@ -105,18 +122,48 @@
generate();
navigator.clipboard.writeText(document.getElementById("out").innerHTML);
}
function addNamedParameters(obj) {
function addNamedParameters(obj, ignore = ["type", "language"]) {
let out = "";
for (const key in obj) {
if (obj[key] == "" || ignore.includes(key)) continue;
out += `|${key}=${obj[key]}`;
}
return out;
}
function loadPresetList() {
const items = {...localStorage};
const items = {...localStorage}; delete items.latestPreset;
for (const key in items) {
addPresetToMenu(key);
}
console.log(localStorage.getItem("latestPreset"));
loadPreset(localStorage.getItem("latestPreset"));
}
function generatePropertyInputs() {
for (const key in parameters) {
const label = document.createElement("label");
label.innerText = parameters[key].label;
let input;
if (parameters[key].type === "dropdown") {
input = document.createElement("select");
for (const optionName in parameters[key].fields) {
const option = document.createElement("option");
option.value = optionName;
option.innerText = parameters[key].fields[optionName];
input.appendChild(option)
}
} else if (parameters[key].type === "textarea") {
input = document.createElement("textarea");
input.cols = 60;
input.rows = 6;
} else {
input = document.createElement("input");
input.type = "text";
}
input.id = key;
document.getElementById(parameters[key].section).appendChild(label);
document.getElementById(parameters[key].section).appendChild(input);
}
}
function addPresetToMenu(key) {
const existingPresets = document.querySelectorAll("#presets option");
@ -146,19 +193,17 @@
function loadPreset(presetName) {
document.getElementById("preset-name").value = presetMenu.value;
const parameterValues = JSON.parse(localStorage.getItem(presetName));
console.log(parameterValues)
for (const key in parameterValues) {
document.getElementById(key).value = parameterValues[key];
}
localStorage.setItem("latestPreset", presetName);
}
function deletePreset() {
const presetName = document.getElementById("preset-name").value;
localStorage.removeItem(presetName);
const existingPresets = presetMenu.children;
let currentPresetOptionNode;
console.log(presetName);
for (const node of existingPresets) {
console.log(node.value);
if (node.value === presetName) {
currentPresetOptionNode = node;
break;