Raum-Modal: Gruppen als Tabs, Jalousien senkrecht bedienen
Die Gruppenueberschriften sind Tabs geworden, Beschattung zuerst - das ist es, was man in einem Raum am haeufigsten anfasst. Vorher scrollte man an drei Rollladen vorbei, um zum Licht zu kommen. Bei nur einer Gruppe bleibt die Leiste weg; auf schmalen Schirmen scrollt sie seitwaerts, statt die Namen umzubrechen. Bei den Jalousien stehen Auf, Stop und Zu jetzt untereinander - so zeigen die Knoepfe in die Richtung, in die sie fahren. Die Hoehe daneben ist ein senkrechter Regler mit "oben" und "unten" an den Enden: der Griff steht dort, wo der Rollladen steht, und niemand muss "100 %" uebersetzen. Die Neigung hat ein Bild dazubekommen. "30 %" oder "70 %" sagt nicht, ob man noch hinaussieht; vier Streifen sagen es. Gezeichnet wird die Hoehe, die eine gekippte Lamelle von vorn zeigt (w * sin(Winkel)) - bei "auf" sieht man nur ihre Kante und viel Luft dazwischen, bei "zu" deckt sie den Abstand zur naechsten vollstaendig ab. Genau das, was das Licht abhaelt. Die Regler faerben ihre Bahn jetzt mit, wie es der Temperaturregler seit jeher tut - dieselbe Eigenschaft --background-size, nur beim senkrechten von oben nach unten. css/solar.css hatte gemischte Zeilenenden und ist dabei durchgehend auf LF gebracht worden; das erklaert den grossen Diff bei kleiner Aenderung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+164
-24
@@ -137,18 +137,72 @@ function bedienform($d)
|
||||
return "sonstiges";
|
||||
}
|
||||
|
||||
/** Ueberschriften der Gruppen, in der Reihenfolge, in der sie erscheinen. */
|
||||
/**
|
||||
* Die Gruppen in der Reihenfolge, in der ihre Tabs erscheinen.
|
||||
*
|
||||
* Beschattung zuerst: das ist es, was man in einem Raum am haeufigsten
|
||||
* anfasst. Messwerte zuletzt - die schaut man an, man bedient sie nicht.
|
||||
*/
|
||||
function raumGruppenTitel()
|
||||
{
|
||||
return [
|
||||
"beschattung" => ["Beschattung", "bi-blinds"],
|
||||
"licht" => ["Licht", "bi-lightbulb"],
|
||||
"schalter" => ["Schalten", "bi-toggle-on"],
|
||||
"sonstiges" => ["Weitere Geräte", "bi-sliders"],
|
||||
"sonstiges" => ["Geräte", "bi-sliders"],
|
||||
"messwerte" => ["Messwerte", "bi-speedometer2"],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Geraetegruppen als Tabs.
|
||||
*
|
||||
* Vorher standen sie untereinander, und man scrollte an drei Rollladen
|
||||
* vorbei, um zum Licht zu kommen. Bei nur einer Gruppe bleibt die Leiste
|
||||
* weg - ein einzelner Tab beschriftet nur sich selbst.
|
||||
*/
|
||||
function zeichneGruppen($gruppen)
|
||||
{
|
||||
$vorhanden = [];
|
||||
foreach (raumGruppenTitel() as $form => $titel) {
|
||||
if (!empty($gruppen[$form])) {
|
||||
$vorhanden[$form] = $titel;
|
||||
}
|
||||
}
|
||||
if (!$vorhanden) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$html = "";
|
||||
if (count($vorhanden) > 1) {
|
||||
$html .= "<ul class='nav nav-pills flex-nowrap gap-1 mb-2 raum-tabs' role='tablist'>";
|
||||
$erster = true;
|
||||
foreach ($vorhanden as $form => $titel) {
|
||||
$html .= "<li class='nav-item' role='presentation'>"
|
||||
. "<button class='nav-link" . ($erster ? " active" : "") . "' type='button'"
|
||||
. " data-bs-toggle='tab' data-bs-target='#raumtab-" . $form . "' role='tab'>"
|
||||
. "<i class='bi " . $titel[1] . "'></i>"
|
||||
. "<span class='ms-1'>" . htmlspecialchars($titel[0]) . "</span>"
|
||||
. "</button></li>";
|
||||
$erster = false;
|
||||
}
|
||||
$html .= "</ul>";
|
||||
}
|
||||
|
||||
$html .= "<div class='tab-content'>";
|
||||
$erster = true;
|
||||
foreach ($vorhanden as $form => $titel) {
|
||||
$html .= "<div class='tab-pane fade" . ($erster ? " show active" : "") . "'"
|
||||
. " id='raumtab-" . $form . "' role='tabpanel'>";
|
||||
foreach ($gruppen[$form] as $d) {
|
||||
$html .= zeichneGeraet($d, $form);
|
||||
}
|
||||
$html .= "</div>";
|
||||
$erster = false;
|
||||
}
|
||||
return $html . "</div>";
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Bausteine
|
||||
// ===========================================================================
|
||||
@@ -178,20 +232,109 @@ function karteZu()
|
||||
*/
|
||||
function reglerZeile($titel, $cmd, $param, $wert, $einheit = "%")
|
||||
{
|
||||
$min = $param["min"] === null ? 0 : intval($param["min"]);
|
||||
$max = $param["max"] === null ? 100 : intval($param["max"]);
|
||||
$wert = $wert === null || $wert === "" ? $min : intval($wert);
|
||||
$wert = max($min, min($max, $wert));
|
||||
$min = reglerMin($param);
|
||||
$max = reglerMax($param);
|
||||
$wert = reglerWert($wert, $min, $max);
|
||||
return "<div class='raum-regler' data-cmd='" . intval($cmd["id"]) . "'"
|
||||
. " data-param='" . intval($param["id"]) . "'>"
|
||||
. "<div class='d-flex justify-content-between small'>"
|
||||
. "<span>" . htmlspecialchars($titel) . "</span>"
|
||||
. "<span class='raum-regler-wert fw-semibold'>" . $wert . $einheit . "</span></div>"
|
||||
. "<input type='range' class='form-range range-color-track' min='" . $min . "' max='" . $max . "'"
|
||||
. " step='1' value='" . $wert . "' data-einheit='" . htmlspecialchars($einheit, ENT_QUOTES) . "'>"
|
||||
. reglerFeld($min, $max, $wert, $einheit)
|
||||
. "</div>";
|
||||
}
|
||||
|
||||
function reglerMin($param)
|
||||
{
|
||||
return $param["min"] === null ? 0 : intval($param["min"]);
|
||||
}
|
||||
|
||||
function reglerMax($param)
|
||||
{
|
||||
return $param["max"] === null ? 100 : intval($param["max"]);
|
||||
}
|
||||
|
||||
function reglerWert($wert, $min, $max)
|
||||
{
|
||||
$wert = $wert === null || $wert === "" ? $min : intval($wert);
|
||||
return max($min, min($max, $wert));
|
||||
}
|
||||
|
||||
function reglerFeld($min, $max, $wert, $einheit)
|
||||
{
|
||||
return "<input type='range' class='form-range range-color-track' min='" . $min . "' max='" . $max . "'"
|
||||
. " step='1' value='" . $wert . "' data-einheit='" . htmlspecialchars($einheit, ENT_QUOTES) . "'>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Die beiden Endstellungen in Worten.
|
||||
*
|
||||
* "Position 100 %" muss man uebersetzen, "unten" nicht. Dazwischen bleibt es
|
||||
* bei der Zahl - fuer halb heruntergefahren gibt es kein Wort. Ausgewertet
|
||||
* wird das Attribut in raumBedienungAktivieren(), js/solar/homeMQTT.js.
|
||||
*/
|
||||
function worteAttribut($beiNull, $beiHundert)
|
||||
{
|
||||
return " data-worte='" . htmlspecialchars(
|
||||
json_encode([0 => $beiNull, 100 => $beiHundert], JSON_UNESCAPED_UNICODE), ENT_QUOTES) . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Hoehe als senkrechter Regler - oben ist oben.
|
||||
*
|
||||
* Einen waagerechten Schieber fuer eine Bewegung, die hoch und runter geht,
|
||||
* muss man erst uebersetzen; senkrecht steht der Griff dort, wo der Rollladen
|
||||
* steht.
|
||||
*/
|
||||
function positionsRegler($cmd, $param, $wert)
|
||||
{
|
||||
$min = reglerMin($param);
|
||||
$max = reglerMax($param);
|
||||
$wert = reglerWert($wert, $min, $max);
|
||||
return "<div class='raum-regler raum-position' data-cmd='" . intval($cmd["id"]) . "'"
|
||||
. " data-param='" . intval($param["id"]) . "'" . worteAttribut("oben", "unten") . ">"
|
||||
. "<span class='raum-ende'>oben</span>"
|
||||
. reglerFeld($min, $max, $wert, "%")
|
||||
. "<span class='raum-ende'>unten</span>"
|
||||
. "</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Lamellenstellung mit einem Bild daneben.
|
||||
*
|
||||
* Bei 30 % oder 70 % sagt die Zahl nicht, ob man noch hinaussieht. Die vier
|
||||
* Streifen zeigen es: schmal mit Luft dazwischen heisst offen, geschlossen
|
||||
* liegen sie aneinander. Gezeichnet wird die Hoehe, die eine gekippte
|
||||
* Lamelle von vorn zeigt - genau das, was das Licht abhaelt.
|
||||
*/
|
||||
function neigungsRegler($cmd, $param, $wert)
|
||||
{
|
||||
$min = reglerMin($param);
|
||||
$max = reglerMax($param);
|
||||
$wert = reglerWert($wert, $min, $max);
|
||||
return "<div class='raum-regler raum-neigung raum-neigung-block'"
|
||||
. " data-cmd='" . intval($cmd["id"]) . "'"
|
||||
. " data-param='" . intval($param["id"]) . "'" . worteAttribut("auf", "zu") . ">"
|
||||
. "<div class='d-flex justify-content-between small'>"
|
||||
. "<span>Neigung</span>"
|
||||
. "<span class='raum-regler-wert fw-semibold'>" . $wert . "%</span></div>"
|
||||
. lamellenBild()
|
||||
. reglerFeld($min, $max, $wert, "%")
|
||||
. "<div class='d-flex justify-content-between raum-ende'><span>auf</span><span>zu</span></div>"
|
||||
. "</div>";
|
||||
}
|
||||
|
||||
/** Die vier Lamellen. Ihre Hoehe setzt der Browser, siehe homeMQTT.js. */
|
||||
function lamellenBild()
|
||||
{
|
||||
$html = "<svg class='raum-lamellen' viewBox='0 0 100 40' preserveAspectRatio='none' aria-hidden='true'>";
|
||||
foreach ([5, 15, 25, 35] as $mitte) {
|
||||
$html .= "<rect class='raum-lamelle' x='0' width='100' data-mitte='" . $mitte . "'"
|
||||
. " y='" . ($mitte - 1) . "' height='2'></rect>";
|
||||
}
|
||||
return $html . "</svg>";
|
||||
}
|
||||
|
||||
/** Kippschalter mit dem Stand, den das Geraet zuletzt gemeldet hat. */
|
||||
function kippSchalter($d, $schalter, $an)
|
||||
{
|
||||
@@ -291,28 +434,32 @@ function zeichneBeschattung($d)
|
||||
}));
|
||||
|
||||
$html = karteAuf($d, $status);
|
||||
$html .= "<div class='raum-jalousie'>";
|
||||
|
||||
// Auf, Stop, Zu untereinander: so zeigen die Knoepfe in die Richtung, in
|
||||
// die sie fahren.
|
||||
if ($auf || $stop || $zu) {
|
||||
$html .= "<div class='d-flex align-items-center gap-2 mb-2'>";
|
||||
$html .= "<div class='btn-group btn-group-sm flex-grow-1' role='group'>";
|
||||
$html .= "<div class='btn-group-vertical btn-group-sm raum-fahrt' role='group'>";
|
||||
foreach ([[$auf, "bi-chevron-up", "Auf"], [$stop, "bi-stop-fill", "Stop"],
|
||||
[$zu, "bi-chevron-down", "Zu"]] as $k) {
|
||||
if (!$k[0]) {
|
||||
continue;
|
||||
}
|
||||
$html .= "<button type='button' class='btn btn-outline-primary' data-cmd='" . intval($k[0]["id"]) . "'"
|
||||
. " title='" . htmlspecialchars($k[2], ENT_QUOTES) . "'>"
|
||||
. "<i class='bi " . $k[1] . "'></i><span class='d-none d-sm-inline ms-1'>"
|
||||
. htmlspecialchars($k[2]) . "</span></button>";
|
||||
. " title='" . htmlspecialchars($k[2], ENT_QUOTES) . "'"
|
||||
. " aria-label='" . htmlspecialchars($k[2], ENT_QUOTES) . "'>"
|
||||
. "<i class='bi " . $k[1] . "'></i></button>";
|
||||
}
|
||||
$html .= "</div>" . mehrMenue($rest) . "</div>";
|
||||
$html .= "</div>";
|
||||
}
|
||||
if ($position) {
|
||||
$html .= reglerZeile("Position", $position, $position["params"][0], $standPos);
|
||||
$html .= positionsRegler($position, $position["params"][0], $standPos);
|
||||
}
|
||||
if ($neigung) {
|
||||
$html .= reglerZeile("Neigung", $neigung, $neigung["params"][0], $standNeigung);
|
||||
$html .= neigungsRegler($neigung, $neigung["params"][0], $standNeigung);
|
||||
}
|
||||
return $html . karteZu();
|
||||
$html .= mehrMenue($rest);
|
||||
return $html . "</div>" . karteZu();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -537,10 +684,3 @@ function zeichneGeraet($d, $form)
|
||||
default: return zeichneSonstiges($d);
|
||||
}
|
||||
}
|
||||
|
||||
/** Ueberschrift einer Gruppe. */
|
||||
function gruppenTitel($titel, $symbol)
|
||||
{
|
||||
return "<h6 class='raum-gruppe text-body-secondary'>"
|
||||
. "<i class='bi " . $symbol . " me-1'></i>" . htmlspecialchars($titel) . "</h6>";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user