munin/static/aehnlich.js

96 lines
3.6 KiB
JavaScript

// „Gibt es schon?" — zeigt beim Anlegen eines Eintrags vorhandene Einträge mit
// ähnlichem Titel an (AUSBAUSTUFEN.md 5.7).
//
// Agenten bekommen bei "remember" eine Rückfrage, wenn es schon einen
// ähnlichen Eintrag gibt. Menschen im Formular bekommen denselben Hinweis,
// nur ohne Sperre: Die Liste erscheint unter dem Titel, speichern lässt sich
// trotzdem. Geprüft wird auf dem Server mit derselben Logik wie bei MCP
// (internal/dubletten), damit beide Wege gleich urteilen.
//
// Gefragt wird erst, wenn eine Weile nicht getippt wurde (wartezeit), nicht
// bei jedem Buchstaben. Antworten, die zu spät für den aktuellen Titel
// kommen, werden verworfen.
(function () {
"use strict";
var titel = document.querySelector("input[data-aehnlich-url]");
var kasten = document.querySelector("[data-aehnlich-liste]");
if (!titel || !kasten) {
return;
}
var liste = kasten.querySelector("ul");
var bezeichner = document.querySelector("input[name=slug]");
var url = titel.getAttribute("data-aehnlich-url");
// Die Adresse eines Eintrags: aus der Such-URL ".../entries/similar" wird
// ".../e/<slug>".
var eintragsBasis = url.replace(/entries\/similar$/, "e/");
var wartezeit = 400; // Millisekunden ohne Tippen, bevor gefragt wird
var zeitgeber = null;
var letzteFrage = "";
function zeige(kandidaten) {
liste.textContent = "";
kandidaten.forEach(function (k) {
var li = document.createElement("li");
var a = document.createElement("a");
a.href = eintragsBasis + encodeURIComponent(k.slug);
a.target = "_blank";
a.rel = "noopener";
a.textContent = k.title;
li.appendChild(a);
// Die gemeinsamen Wörter zeigen, warum der Eintrag hier steht.
// Ist es nur ein allgemeines Wort, sieht man sofort: anderes Thema.
if (k.gemeinsam && k.gemeinsam.length) {
var grund = document.createElement("span");
grund.className = "hilfe";
grund.textContent = " — gemeinsam: " + k.gemeinsam.join(", ");
li.appendChild(grund);
}
liste.appendChild(li);
});
kasten.hidden = kandidaten.length === 0;
}
function frage() {
var t = titel.value.trim();
var s = bezeichner ? bezeichner.value.trim() : "";
var schluessel = t + "\u0000" + s;
if (schluessel === letzteFrage) {
return;
}
letzteFrage = schluessel;
if (t.length < 3) {
zeige([]);
return;
}
var adresse = url + "?title=" + encodeURIComponent(t) + "&slug=" + encodeURIComponent(s);
fetch(adresse, { credentials: "same-origin", headers: { "Accept": "application/json" } })
.then(function (antwort) { return antwort.ok ? antwort.json() : []; })
.then(function (kandidaten) {
// Inzwischen weitergetippt? Dann gehört die Antwort zu einem
// alten Titel.
if (schluessel === letzteFrage) {
zeige(kandidaten || []);
}
})
.catch(function () { /* nur ein Hinweis — ohne ihn geht es auch */ });
}
function spaeterFragen() {
clearTimeout(zeitgeber);
zeitgeber = setTimeout(frage, wartezeit);
}
titel.addEventListener("input", spaeterFragen);
if (bezeichner) {
bezeichner.addEventListener("input", spaeterFragen);
}
// Vorbelegter Titel (z.B. nach einem Fehler zurück im Formular).
if (titel.value.trim() !== "") {
frage();
}
})();