Raum-Modal Licht: Preset als Chips, Effekt als durchsuchbarer Picker, WLED-Zustand live
Die native Auswahlliste zeichnete Chrome hell auf hell. Welcher Effekt und welches Preset gerade laufen, liest room.php?action=wled direkt von der Lampe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+79
-11
@@ -620,18 +620,86 @@ function rfLampeStarten(karte) {
|
||||
eigen.addEventListener("change", () => setzen(eigen.value));
|
||||
}
|
||||
|
||||
// Effekt und Preset: Chips oder - bei langen Listen - eine Auswahl.
|
||||
karte.querySelectorAll(".rf-effekte .rf-chips[data-cmd]").forEach(gruppe => {
|
||||
gruppe.querySelectorAll("[data-wert]").forEach(k => k.addEventListener("click", () => {
|
||||
gruppe.querySelectorAll("[data-wert]").forEach(x => x.setAttribute("aria-pressed", String(x === k)));
|
||||
// Preset, Effekt und andere Listen: Chips, lange Listen im aufklappbaren
|
||||
// Picker mit Suche.
|
||||
karte.querySelectorAll(".rf-liste").forEach(liste => {
|
||||
const knopf = liste.querySelector(".rf-picker-knopf");
|
||||
const picker = liste.querySelector(".rf-picker");
|
||||
const suche = liste.querySelector(".rf-suche");
|
||||
const auf = offen => {
|
||||
if (!picker) return;
|
||||
picker.hidden = !offen;
|
||||
knopf.setAttribute("aria-expanded", String(offen));
|
||||
if (offen) {
|
||||
suche.value = "";
|
||||
liste.querySelectorAll("[data-wert]").forEach(k => { k.hidden = false; });
|
||||
const gewaehlt = liste.querySelector("[data-wert][aria-pressed='true']");
|
||||
if (gewaehlt) gewaehlt.scrollIntoView({ block: "nearest" });
|
||||
suche.focus({ preventScroll: true });
|
||||
}
|
||||
};
|
||||
if (knopf) knopf.addEventListener("click", () => auf(picker.hidden));
|
||||
if (suche) {
|
||||
suche.addEventListener("input", () => {
|
||||
const text = suche.value.trim().toLowerCase();
|
||||
liste.querySelectorAll("[data-wert]").forEach(k => { k.hidden = text !== "" && !k.textContent.toLowerCase().includes(text); });
|
||||
});
|
||||
suche.addEventListener("keydown", e => {
|
||||
if (e.key === "Escape") { e.stopPropagation(); auf(false); knopf.focus(); }
|
||||
if (e.key === "Enter") {
|
||||
const erster = [...liste.querySelectorAll("[data-wert]")].find(k => !k.hidden);
|
||||
if (erster) erster.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
liste.querySelectorAll("[data-wert]").forEach(k => k.addEventListener("click", () => {
|
||||
rfListeSetzen(liste, k.dataset.wert);
|
||||
auf(false);
|
||||
const params = {};
|
||||
params[gruppe.dataset.param] = k.dataset.wert;
|
||||
rfKommando(Number(gruppe.dataset.cmd), params, gruppe);
|
||||
params[liste.dataset.param] = k.dataset.wert;
|
||||
rfKommando(Number(liste.dataset.cmd), params, liste);
|
||||
}));
|
||||
});
|
||||
karte.querySelectorAll(".rf-effekte select[data-cmd]").forEach(auswahl => auswahl.addEventListener("change", () => {
|
||||
const params = {};
|
||||
params[auswahl.dataset.param] = auswahl.value;
|
||||
rfKommando(Number(auswahl.dataset.cmd), params, auswahl);
|
||||
}));
|
||||
|
||||
if (karte.dataset.wled) rfWledLesen(karte);
|
||||
}
|
||||
|
||||
/** Einen Eintrag einer Liste als gewaehlt zeigen; null = keiner. */
|
||||
function rfListeSetzen(liste, wert) {
|
||||
let name = null;
|
||||
liste.querySelectorAll("[data-wert]").forEach(k => {
|
||||
const ja = wert !== null && k.dataset.wert === String(wert);
|
||||
k.setAttribute("aria-pressed", String(ja));
|
||||
if (ja) name = k.textContent;
|
||||
});
|
||||
const anzeige = liste.querySelector("[data-rf-picker-wert]");
|
||||
if (anzeige) anzeige.textContent = name === null ? "–" : name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Den wirklichen Zustand einer WLED-Lampe holen. In der Datenbank stehen nur
|
||||
* an/aus, Helligkeit und Farbe vom letzten Poll; welcher Effekt und welches
|
||||
* Preset laufen, weiss nur die Lampe selbst.
|
||||
*/
|
||||
function rfWledLesen(karte) {
|
||||
rfRequest("wled", { actor: Number(karte.dataset.actor) }).then(stand => {
|
||||
if (!stand || stand.error || !document.body.contains(karte)) return;
|
||||
karte.dataset.an = stand.an ? "1" : "";
|
||||
const hell = karte.querySelector(".rf-hell");
|
||||
if (hell && stand.bri !== null && document.activeElement !== hell) hell.value = stand.bri;
|
||||
if (stand.farbe && (stand.farbe[0] || stand.farbe[1] || stand.farbe[2])) {
|
||||
const hex = "#" + stand.farbe.map(v => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("");
|
||||
karte.style.setProperty("--farbe", hex);
|
||||
const eigen = karte.querySelector(".rf-farbe-eigen input");
|
||||
if (eigen) eigen.value = hex;
|
||||
karte.querySelectorAll("[data-farbe]").forEach(k => k.setAttribute("aria-pressed", String(k.dataset.farbe === hex)));
|
||||
}
|
||||
karte.querySelectorAll(".rf-liste").forEach(liste => {
|
||||
const wert = stand[liste.dataset.feld];
|
||||
// WLED meldet ps = -1, wenn kein Preset aktiv ist.
|
||||
if (typeof wert !== "undefined") rfListeSetzen(liste, wert === null || wert < 0 ? null : wert);
|
||||
});
|
||||
rfLampeZeichnen(karte);
|
||||
rfStatus();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user