Kachelsymbole: jedes Bootstrap-Icon statt einer Handvoll
Fuer die Symbole vor den Zahlen standen drei Codepunkte von Hand in rooms.php, und die Maske bot genau diese drei an. Jedes weitere Symbol waere eine Codeaenderung gewesen. Die Codepunkte stehen aber schon im Haus: css/bootstrap-icons.min.css fuehrt sie unter .bi-<name>::before - dieselbe Quelle, aus der auch der Browser liest. bootstrapIcons() liest sie von dort (2078 Stueck, einmal je Anfrage), kachelIcon() schlaegt darin nach. Damit ist jedes Symbol moeglich, und ein Versionswechsel der Icons zieht von selbst mit. In der Maske steht deshalb kein Auswahlfeld mehr, sondern der Name mit einer Vorschau davor - "moisture" sagt nichts, das Symbol daneben schon. Die Vorschlagsliste beginnt mit gut dreissig ueblichen Symbolen unter deutscher Beschriftung (Temperatur, Feuchte, Leistung, Wallbox, Regen ...), danach folgt der ganze Rest alphabetisch. Ein Name, den es nicht gibt, zeigt sofort ein rotes Fragezeichen und wird beim Speichern mit Begruendung abgelehnt. In der eingeklappten Kurzfassung einer Kachel steht das Symbol jetzt mit - es ist das schnellste Erkennungszeichen dafuer, welcher der drei Werte gemeint ist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+75
-10
@@ -376,9 +376,14 @@ function zeichneKacheln() {
|
||||
/** Eine Raumzeile: Name, Kurzfassung der Werte, darunter der Editor. */
|
||||
function kachelZeile(k) {
|
||||
const werte = k._entwurf || k.werte;
|
||||
// Das Symbol steht auch in der Kurzfassung: es ist das, was auf der Kachel
|
||||
// vor der Zahl steht, und damit der schnellste Weg zu erkennen, welcher der
|
||||
// drei Werte gemeint ist.
|
||||
const kurz = werte.length
|
||||
? werte.map(w => '<span class="kachel-chip">' + textSchuetzen(kachelWertKurz(w, k))
|
||||
+ "</span>").join("")
|
||||
? werte.map(w => '<span class="kachel-chip">'
|
||||
+ (w.icon && kachelSymbolBekannt(w.icon)
|
||||
? '<i class="bi bi-' + textSchuetzen(w.icon) + '"></i>' : "")
|
||||
+ textSchuetzen(kachelWertKurz(w, k)) + "</span>").join("")
|
||||
: '<span class="kachel-chip leer">ohne Messwert</span>';
|
||||
|
||||
let html = '<div class="kachel-zeile' + (k._offen ? " offen" : "") + '"'
|
||||
@@ -407,6 +412,59 @@ function kachelZeile(k) {
|
||||
return html + "</div>";
|
||||
}
|
||||
|
||||
/* --- Symbole ------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Das Feld für das Symbol: eine Vorschau und ein Name.
|
||||
*
|
||||
* Statt einer Auswahlliste mit einer Handvoll Symbole steht hier der Name des
|
||||
* Bootstrap-Icons - damit sind alle gut zweitausend möglich, ohne dass für
|
||||
* jedes neue eines im Code nachgetragen werden müsste. Die üblichen stehen in
|
||||
* der Vorschlagsliste obenan, mit deutscher Beschriftung; wer ein anderes
|
||||
* will, tippt und bekommt den Rest angeboten (icons.getbootstrap.com).
|
||||
*
|
||||
* Die Vorschau ist die eigentliche Hilfe: ein Name wie "moisture" sagt nichts,
|
||||
* das Symbol daneben schon.
|
||||
*/
|
||||
function kachelSymbolFeld(icon) {
|
||||
return '<span class="kw-symbol-schau">' + kachelSymbolVorschau(icon) + "</span>"
|
||||
+ '<input type="text" class="form-control form-control-sm" data-feld="icon"'
|
||||
+ ' list="kachelIcons" placeholder="Symbol" autocomplete="off"'
|
||||
+ ' value="' + textSchuetzen(icon) + '">';
|
||||
}
|
||||
|
||||
/** Der Inhalt der Vorschau: das Symbol, ein Strich, oder ein Fragezeichen. */
|
||||
function kachelSymbolVorschau(icon) {
|
||||
if (!icon) return '<i class="bi bi-dash" title="ohne Symbol"></i>';
|
||||
if (!kachelSymbolBekannt(icon)) {
|
||||
return '<i class="bi bi-question-circle unbekannt" title="Dieses Symbol gibt es nicht"></i>';
|
||||
}
|
||||
return '<i class="bi bi-' + textSchuetzen(icon) + '" title="' + textSchuetzen(icon) + '"></i>';
|
||||
}
|
||||
|
||||
function kachelSymbolBekannt(icon) {
|
||||
if (!kachelSymbolBekannt._satz) {
|
||||
kachelSymbolBekannt._satz = new Set((kachelModell.symbole || []).map(s => s.name));
|
||||
}
|
||||
return kachelSymbolBekannt._satz.has(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Vorschlagsliste steht einmal im Dokument, nicht in jeder Zeile.
|
||||
*
|
||||
* Zweitausend Einträge sind rund siebzig Kilobyte Markup; bei jedem
|
||||
* Neuzeichnen einer Kachel neu zu bauen waere Verschwendung. Sie haengt
|
||||
* deshalb am Ende des Dokuments und ueberlebt das Neuzeichnen der Liste.
|
||||
*/
|
||||
function kachelIconListeSicherstellen() {
|
||||
if (document.getElementById("kachelIcons")) return;
|
||||
const liste = document.createElement("datalist");
|
||||
liste.id = "kachelIcons";
|
||||
liste.innerHTML = (kachelModell.symbole || []).map(s => '<option value="' + s.name + '"'
|
||||
+ (s.titel ? ' label="' + textSchuetzen(s.titel) + '"' : "") + ">").join("");
|
||||
document.body.appendChild(liste);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eine Wertdefinition als Formularzeile.
|
||||
*
|
||||
@@ -418,11 +476,6 @@ function kachelZeile(k) {
|
||||
function kachelWertZeile(wert, i, kachel) {
|
||||
const quelle = kachelQuelle(wert);
|
||||
const katalog = (kachelModell && kachelModell.katalog) || [];
|
||||
const symbole = kachelModell.symbole || {};
|
||||
const symbolOptionen = Object.keys(symbole).map(function (key) {
|
||||
return '<option value="' + key + '"' + ((wert.icon || "") === key ? " selected" : "")
|
||||
+ ">" + textSchuetzen(symbole[key]) + "</option>";
|
||||
}).join("");
|
||||
|
||||
// Eingabeart. "Messwert" steht nur zur Wahl, wenn es einen Katalog gibt -
|
||||
// ohne Mesh-Datenbank waere es eine leere Liste.
|
||||
@@ -516,8 +569,7 @@ function kachelWertZeile(wert, i, kachel) {
|
||||
+ (wert.format === "leistung" ? " disabled" : "")
|
||||
+ ' value="' + (wert.stellen === undefined ? "" : wert.stellen) + '"></div>'
|
||||
|
||||
+ '<div class="kw-symbol"><select class="form-select form-select-sm" data-feld="icon">'
|
||||
+ symbolOptionen + "</select></div>"
|
||||
+ '<div class="kw-symbol">' + kachelSymbolFeld(wert.icon || "") + "</div>"
|
||||
|
||||
+ '<div class="kw-schalter">'
|
||||
+ '<label title="Leistung: skaliert selbst zwischen W und kW">'
|
||||
@@ -584,7 +636,7 @@ function kachelWertLesen(feldZeile) {
|
||||
const stellen = hol("stellen");
|
||||
if (stellen !== "" && stellen !== undefined) wert.stellen = parseInt(stellen, 10);
|
||||
}
|
||||
const icon = hol("icon");
|
||||
const icon = (hol("icon") || "").trim();
|
||||
if (icon) wert.icon = icon;
|
||||
if (hol("gross")) wert.gross = true;
|
||||
return wert;
|
||||
@@ -627,6 +679,8 @@ async function kachelnHolen() {
|
||||
const d = await antwort.json();
|
||||
if (!antwort.ok || d.error) throw new Error(d.error || "HTTP " + antwort.status);
|
||||
kachelModell = d;
|
||||
delete kachelSymbolBekannt._satz; // neue Antwort, neue Namen
|
||||
kachelIconListeSicherstellen();
|
||||
zeichneKacheln();
|
||||
} catch (e) {
|
||||
ziel.innerHTML = '<div class="alert alert-danger mb-0">Kacheln nicht abrufbar: '
|
||||
@@ -715,6 +769,17 @@ function kachelnBinden() {
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Die Vorschau folgt dem Tippen. Neu gezeichnet wird dafuer nicht - das
|
||||
* naehme dem Feld nach jedem Buchstaben den Cursor.
|
||||
*/
|
||||
liste.addEventListener("input", function (ereignis) {
|
||||
const feld = ereignis.target.closest('[data-feld="icon"]');
|
||||
if (!feld) return;
|
||||
const schau = feld.parentElement.querySelector(".kw-symbol-schau");
|
||||
if (schau) schau.innerHTML = kachelSymbolVorschau(feld.value.trim());
|
||||
});
|
||||
|
||||
const neuLaden = document.getElementById("kachelNeuLaden");
|
||||
if (neuLaden) neuLaden.addEventListener("click", kachelnHolen);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user