// experimentellt script för att sortera innehåll i mallar i bokstavsordning
// sorteringsknapparna dyker automatiskt upp vid osorterade mallar, till vänster om textfältet
/*
* Kända problem/buggar:
* uppdelning av element innehållande kommatecken
* ex: "] - ''ur form, ej i form''" på sidan "slag" (https://sv.wiktionary.orghttps://sv.wiktionary.org/w/index.php?title=slag&oldid=3807843)
*/
function updateSortButtons() {
const textArea = document.getElementById("wpTextbox1");
const icon = `
<svg viewBox="0 0 100 100">
<path stroke="#000" fill="none" stroke-width="5" d="m9,20 h79 m-10,-10 10,10 -10,10"/>
<text x="9" y="85" font-family="sans-serif" font-size="50">A Ö</text>
</svg>
`;
const listTemplates = [
"synonymer",
"antonymer",
"smeknamn",
"hyperonymer",
"hyponymer",
"kohyponymer",
"holonymer",
"meronymer",
"komeronymer",
"troponymer",
"varianter",
"anagram",
"jämför",
"homofoner",
"besläktade ord",
"sammansättningar",
"fraser",
"seäven"
];
for (const e of document.querySelectorAll(".sort-button")) {
e.remove();
}
const templateLineRegex = new RegExp("^#?: *\\{\\{(" + listTemplates.join("|") + ")\\|*\\}\\} *$");
const lines = textArea.value.split("\n");
const unsortedTemplateLineIndices = ;
for (let i = 0; i < lines.length; i++) {
if (templateLineRegex.test(lines) && !isSorted(lines)) {
unsortedTemplateLineIndices.push(i);
}
}
if (unsortedTemplateLineIndices.length == 0) return;
const lineCoords = getLineCoordinates(textArea);
const textAreaTop = textArea.getBoundingClientRect().top + window.scrollY;
const textAreaLeft = textArea.getBoundingClientRect().left;
for (const i of unsortedTemplateLineIndices) {
if (templateLineRegex.test(lines)) {
const btn = document.createElement("button");
btn.className = "sort-button";
btn.style.top = (lineCoords + textAreaTop - textArea.scrollTop) + "px";
btn.style.left = (textAreaLeft - 15) + "px";
btn.innerHTML = icon;
btn.dataset.y = lineCoords + textAreaTop;
btn.dataset.lineIndex = i;
btn.addEventListener("click", sortTemplateList);
document.body.appendChild(btn);
}
}
}
function sortTemplateList() {
const textArea = document.getElementById("wpTextbox1");
const lines = textArea.value.split("\n");
const i = this.dataset.lineIndex;
lines = lines.replace(/^(#?: *\{\{+\|(?:'*\(.*?\)'* ?)?)(.*)\}\} *$/, (_, a, b) => {
return a + sortList(b) + "}}";
});
textArea.value = lines.join("\n");
// we could just call this.remove()
// but it's safer to update all buttons in case any duplicates were removed from the list and line wrapping changes
updateSortButtons();
}
function isSorted(line) {
const list = line.match(/^#?: *\{\{+\|(?:'*\(.*?\)'* ?)?(.*)\}\} *$/);
return list == sortList(list);
}
function sortList(list) {
// replaceAll(/\/g, "") is necessary to correctly sort some phrases
// e.g. ] and ] on the page "visa" (https://sv.wiktionary.orghttps://sv.wiktionary.org/w/index.php?title=visa&oldid=3829241)
return list
.split(/,(?!*\]|*\))/)
.map(e => e.trim())
.sort((a, b) => a.replaceAll(/\/g, "").localeCompare(b.replaceAll(/\/g, ""), "sv"))
.filter((e, i, a) => e && e != a) // remove empty elements and duplicates
.join(", ");
}
function getLineCoordinates(textArea) {
textArea = document.getElementById("wpTextbox1");
const div = document.createElement("div");
div.style.width = textArea.clientWidth + "px";
div.style.font = getComputedStyle(textArea).font;
div.style.position = "fixed"; // makes div the offsetParent of its children
for (const line of textArea.value.split("\n")) {
const span = document.createElement("span");
span.innerText = line;
div.appendChild(span);
div.appendChild(document.createElement("br"));
}
document.body.appendChild(div);
const yCoords = Array.from(div.querySelectorAll("span")).map(e => e.offsetTop);
div.remove();
return yCoords;
}
function init() {
const textArea = document.getElementById("wpTextbox1");
if (!textArea) return;
// waiting for animation frames removes stuttering while scrolling
let sortButtonWaitingForAnimation = false;
textArea.addEventListener("scroll", function() {
sortButtonWaitingForAnimation = true;
window.requestAnimationFrame(() => {
for (const e of document.getElementsByClassName("sort-button")) {
e.style.top = (e.dataset.y - this.scrollTop) + "px";
}
sortButtonWaitingForAnimation = false;
});
});
const sortButtonCSS = document.createElement("style");
sortButtonCSS.innerHTML = `
.sort-button {
margin: 0;
border: 0;
padding: 0;
width: 10px;
position: absolute;
background-color: #eee;
}
.sort-button:hover{
background-color: #ccc;
}
`;
document.body.appendChild(sortButtonCSS);
textArea.addEventListener("input", updateSortButtons);
window.addEventListener("resize", updateSortButtons);
updateSortButtons();
}
if (document.readyState == "complete") {
init();
} else {
document.addEventListener("readystatechange", () => {
if (document.readyState == "complete") {
init();
}
});
}