FTUI und jQuery; möglich oder mein Unverständnis (addon swiper) ?

Begonnen von FHEm2005, 04 Mai 2016, 20:17:03

Vorheriges Thema - Nächstes Thema

FHEm2005

Hallo,
Ich habe ein x-beliebiges Widget bei dem das Attribut data-device="devicename1" ist, Da ich mehrere ähnliche devices habe, möchte ich mit jQuery den devicename1 über ein <select>-Element das neue Device auswählen und  "devicename 1" durch den ausgewählten neuen Namen z.B.  "devicename2" ersetzen. Bei der Überprüfung werden brav alle devicename1 durch devicename2 ersetzt. Trotzdem werden alle Aktionen noch mit dem "alten" Namen durchgeführt. Damit bekomme ich auch keine Statusanzeigen.

Beispiel an einer Pausentaste:

<div data-type="switch"
data-device="SB3.Buero"
data-get="playStatus"
data-set-on="play"
data-set-off="pause 1"
data-get-on='["playing","paused","stopped"]'
data-icons='["fa-pause","fa-play","fa-play"]'
data-background-icon="fa-square-o" >
</div>


Jetzt wird über jQuery mit diesem Code;
<script>
$( "select" )
  .change(function () {
    var str = "";
    $( "select option:selected" ).each(function() {
      str += $( this ).text() + " ";
    });
    $( "div" ).attr( "data-device",str );
  })
  .change();
</script>


das data-device="SB3.Buero" in data-device="SBN.Bad" in allen div's ausgetauscht. Der abgesetzte Befehl ist aber immer noch "set SB3.Buero play" und "set SB3.Buero pause 1".

Das Script steht im header-Element.

Kann es sein, dass ich etwas versuche, was durch den FTUI-Code nicht funktionieren kann? Oder wie kann ich FTUI mitteilen, dass das Device sich geändert hat?

Gruß Eberhard

Überschrift angepasst!
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM, BSB-LAN

setstate

Ich muss das dann mal live testen, aber ich würde eine ID vergeben, damit du nur wirklich das eine Element änderst:


<div data-type="switch" id="musicbox"
data-device="SB3.Buero"
data-get="playStatus"
data-set-on="play"
data-set-off="pause 1"
data-get-on='["playing","paused","stopped"]'
data-icons='["fa-pause","fa-play","fa-play"]'
data-background-icon="fa-square-o" >
</div>


und dann data ändern


$('#musicbox').data( "device", str );


ist aber noch ungetestet ...

viegener

Dadurch, dass Du das Attribut data-device setzt wird erstmal nichts geändert an der Anzeige des aktuellen FTUI. Es gibt zentrale Routinen, die aus den widget-Definitionen die devices zusammensammeln und auch die einzelnen Widgetinstanzen initialisieren. Nur dann wird das Attribut neu ausgewertet.

Ich habe versucht etwas ähnliches zu erreichen, leider aber auch noch ohne Lösung.

Ich habe auch schon versucht mit initPage() bzw. initWidgets() weiterzukommen, denn damit wird die Seite neu ausgelesen (Devices gesammelt und widgets ebenfalls initialisiert)

Vielleicht kommst Du damit weiter, ich habe momentan wie gesagt auch noch keine Lösung.
Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

setstate

Ist ja keine Anzeige, der Switch soll senden. Und vorm Senden wird das data Attribute device aus dem DOM gelesen. Eigentlich müsste es so gehen.
Ich probiere das dann mal ...

viegener

Wenn es nur um den set geht ja (Bist Du da sicher, denn es wird in meiner Version auf elem.data('device') zugegriffen) . Ich hatte angenommen, dass auch der Zustand richtig angezeigt werden sollte, da ein data-get angegeben war (und das wird ja nicht aus dem DOM sondern beim init... ausgelesen)


Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

setstate

#5
Dein SCRIPT muss ans Ende des Documents, zwischen </BODY> und </HTML>
Damit das Document schon gelesen wurde bevor das Skript ausgeführt wird. Weil sonst noch kein SELECT Element existiert, wo der 'change' Listener drangehangen werden könnte.

Im Header müsste der Code erst mit dem Document.Ready Event ausgeführt werden


<script>
$(document).ready(function() {
    $( "select" )
      .change(function () {
        var str = "";
        $( "select option:selected" ).each(function() {
          str += $( this ).text() + " ";
        });
        $( "#musicbox" ).data( "device",str );
      })
      .change();
  });
</script>

FHEm2005

Erst einmal vielen Dank an euch für das Interesse an meinem Problem.

Zusätzlichliche Info's:
Ziel meiner "Übung" sollte folgendes Szenrio werden. Ich habe eine Bedienungsoberfläche für die Bedienung meiner Squeezeboxen (SB) gebastelt. Da ich aber mehrere habe, möchte ich sie innerhalb eines widget-Rahmens steuern können. Der Kopf bekommt ein Pulldown-Menu, von dem aus alle SB angewählt werden können. In allen data-devices wird der vorhandene Name gegen den ausgewählten Namen mit jQuery ausgetauscht. Eine Oberfläche für alle SBn
Der <select>-Part hat folgendes aussehen:
<form >
<input class ="play" type="text" value ="Field 1">
<select class="play" name="sqb" size="1" onchange="player=(this.form.sqb.options[this.form.sqb.selectedIndex].value);">
<option value="SB3.Buero" selected="selected">SB3.Buero</option>
<option value="SBT.Buero">SBT.Buero</option>
<option value="SBiP.Eberhard">SBiP.Eberhard</option>
<option value="RX-V477">RX-V477</option>
<option value="SBN.Bad">SBN.Bad</option>
</select>
</form>


Wie zu noch zu sehen ist, hatte ich auch versucht den ausgewählten Wert direkt in die Variable player zu schreiben und dann im jQuery-Teil zu benutzen. Kein Erfolg. Einen Wert habe ich als selected bereits ausgewählt. Das wäre in den gezeigten Fall  die SB3.Büro. Setze ich die Vorauswahl auf einen anderen Wert, wird direkt beim ersten Aufruf das Gerät geändert. Ziel: Jedes Zimmer hat den gleichen Code, nur wird an unterschiedlichen Stellen selected="selected" eingetragen.

@setstate: zu #1 Ob mit id class oder sonst wie. Die Auswahl und der Austauch ist korrekt, aber alle Zustandsabfragen und Befehle sind fehlerhaft. Auch die ursprünglich eingetragene SB3.Buero funktioniert nun nicht mehr.
zu #5:
ZitatIm Header müsste der Code erst mit dem Document.Ready Event ausgeführt werden
Das ist wohl richtig, bringt aber leider keine Veränderung.

@viegener: zu #2:
ZitatIch habe auch schon versucht mit initPage() bzw. initWidgets() weiterzukommen,
. Da meine Kenntnisse begrenzt sind, komme ich auch mit Deinen Hinweisen nicht weiter.
zu 4:
ZitatWenn es nur um den set geht ja (Bist Du da sicher, denn es wird in meiner Version auf elem.data('device') zugegriffen) . Ich hatte angenommen, dass auch der Zustand richtig angezeigt werden sollte, da ein data-get angegeben war (und das wird ja nicht aus dem DOM sondern beim init... ausgelesen)
Es geht nicht nur um set-Befehle.  In der Oberfläche werden die widgets image, label, joinedlabel, switch, select, popup, multistatebutton und slider verwendet.  Den switch hatte ich mir als Testobjekt herausgesucht. Für die Zustandsanzeige wäre wichtig, dass der aktuelle >Z>Ustand ausgelesen wird, wenn das Dok mit JQuery fertig ist. Das ist vmtl. ein weiteres Problem, welches nach dem set-Problem angepackt werden sollte, momentan lassen wir es mal außen vor.

Wenn ich über  <option value="SBN.Bad" selected="selected">SBN.Bad</option> von vornherein die SBN.Bad "voreinstelle" werden die Befehle auch dafür ausgesendet. Abfragen gehen überhaupt nicht.

Gruß Eberhard

Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM, BSB-LAN

setstate

Mein Beispiel von gestern funktioniert aber fürs Senden!

Das Umstellen beim Empfangen ist nicht so einfach, wie du dir das vorstellst. Die Widgets werden am Anfang initialisiert. D.h. alle Parameter die Readings sind und von FHEM kommen, gehen in eine Subscription-Liste und werden nur dann mit Daten gefüttert, wenn diese dem Widget zugeordnet sind. Wenn du alle data-device austauschst, musst du danach 'initWidgets(<area>);' rufen. <area> ist der Container, der die geänderten Widgets enthält, damit nicht die ganze Seite neu initialisiert wird.
Aber zuerst musst du sicher sein, dass alle data-devices richtg ausgetauscht wurden. Dazu setzt man sich console.log('mytext'); Zeilen in den entsprechenden Events, damit man sieht, ob der Basis-Code überhaupt funktioniert. Welchen Wert die data-* Attribute haben, sieht man auch schön im DOM-Inspektor.

Ich würde das aber alle etwas anders realisieren: Ich würde mit dem Swiper mir alle Player nebeneinander anzeigen und dann mit einem Wisch oder mit Pagebutton-oder Link das spezielle Element anwählen. Dann braucht an nix immer wieder neu zu initialisieren

FHEm2005

Hallo setstate,
viel Marterial für viel Stunden testen und spielen. Ich werde mich wieder melden wenn ich durch bin oder aufgegeben haben. ;D ;D ;D
Danke ersteinmal!
Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM, BSB-LAN

FHEm2005

Hallo setstate,
ich habe mich für Deinen Vorschlag entschieden.
Zitat von: setstate am 05 Mai 2016, 14:46:32
Ich würde das aber alle etwas anders realisieren: Ich würde mit dem Swiper mir alle Player nebeneinander anzeigen und dann mit einem Wisch oder mit Pagebutton-oder Link das spezielle Element anwählen. Dann braucht an nix immer wieder neu zu initialisieren
Das habe ich mal versucht: Drei Playersteuerungen neben einander gestellt und in swiper nach dem BASIC-Muster eingebunden. Größe des Fensters sollte 300px x 500px sein. dargestellt werden sollten drei Playersteuerungen in der Größe  482px x 275px.

Meine Fehlerliste:
Das widget slider  und pop-up geht gar nicht mehr.
Von den drei Fenstern wird nur das erste angezeigt.
Der Ausschnitt des swipers gibt ja nur einen kleinen Ausschnitt des Ganzen frei. Deshalb geht das Pop-up im nicht sichtbaren Bereich auf. Die Positionsangaben wurden immer mit position:absolute angegeben worden.
Die drei Punkte haben ihre position irgendwo innerhalb des Rahmens.
Das Pull-down wird zwar angezeigt, hat aber keine Wirkung mehr.
Am rechten Rand fehlt eine breite von ca. 5px, obwohl links noch jede Menge Luft ist. (Kann ich das Fenster (Guckloch) verschieben?)
Am unteren Rand fehlen ebenfalls ca.3px obwohl nach oben Luft wäre.

Ehrlich gesagt weiß ich nicht wo ich anfangen soll.

Gruß Eberhard


Die Erläuterung in Github ist leider nicht  gerade der Bringer...  8) 8)

Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM, BSB-LAN

viegener

Ich habe die Anregung auch mal bei mir umgesetzt (für Charts, aber das grundsätzliche Gerüst sollte passen), anbei mal ein Ausschnitt aus der Seite auf der das bei mir korrekt funktioniert. Allerdings nicht in einem popup (ich habe das direkt auf der Seite). Dis Auswahl erfolgt über ein select widget und das zugehörige Dummy-Device in FHEM.


<li data-row="1" data-col="2" data-sizex="10" data-sizey="4">


    <header>Temperaturen</header>
<div class="cell wider inline">
          <div data-type="label" class="inline wider">Sensor</div>
          <div data-type="select" data-device="ftuiSelectSensor"
                    data-alias='["Aussen","Gaestebad","Wohnzimmer"]'
                    data-items='["temp_aussen","temp_gb","temp_wz"]'
                    data-get="copyState" data-set="" class="w3x" ></div>
          <div></div>
    </div>

    <div data-type="swiper" data-height="400px" data-width="850px" data-get="copyState" data-device="ftuiSelectSensor"
         data-states='["temp_aussen","temp_gb","temp_wz"]'
         class="top-space-2x noswipe ">
      <ul>
          <li data-hash="temp_aussen">
             
  <div data-type="label" class="large center">Aussen</div>

  <div class="normal"
                data-type="chart"
                data-device="temp_aussen"
                data-logdevice='["FileLog_temp_aussen"]'
                data-columnspec='["4:temperature","4:humidity"]'
                data-style='["ftui l2","ftui l6"]'
                data-ptype='["lines","lines"]'
                data-uaxis='["primary","secondary"]'
                data-legend='["Temp", "Hum"]'
                data-yunit="°C"
                data-ytext="Temperatur"
                data-minvalue="auto"
                data-maxvalue="auto"
                data-yunit_sec="%"
                data-ytext_sec="Prozent"
                data-yticks="auto"
                data-minvalue_sec="auto"
                data-maxvalue_sec="auto"
                data-daysago_start="0"
                data-daysago_end="-1"
                data-crosshair="true"
                data-cursorgroup="1"
                data-scrollgroup="1"
                data-showlegend="true"
                data-xticks="auto"
                data-height="300px">
           </div>
   

          </li>
          <li data-hash="temp_gb">
             
  <div data-type="label" class="large center">Gästebad</div>

  <div class="normal"
                data-type="chart"
                data-device="temp_gb"
                data-logdevice='["FileLog_temp_gb"]'
                data-columnspec='["4:temperature","4:humidity"]'
                data-style='["ftui l2","ftui l6"]'
                data-ptype='["lines","lines"]'
                data-uaxis='["primary","secondary"]'
                data-legend='["Temp", "Hum"]'
                data-yunit="°C"
                data-ytext="Temperatur"
                data-minvalue="auto"
                data-maxvalue="auto"
                data-yunit_sec="%"
                data-ytext_sec="Prozent"
                data-yticks="auto"
                data-minvalue_sec="auto"
                data-maxvalue_sec="auto"
                data-daysago_start="0"
                data-daysago_end="-1"
                data-crosshair="true"
                data-cursorgroup="1"
                data-scrollgroup="1"
                data-showlegend="true"
                data-xticks="auto"
                data-height="300px">
           </div>
   

          </li>
          <li data-hash="temp_wz">
             
  <div data-type="label" class="large center">Wohnzimmer</div>

  <div class="normal"
                data-type="chart"
                data-device="temp_wz"
                data-logdevice='["FileLog_temp_wz"]'
                data-columnspec='["4:temperature","4:humidity"]'
                data-style='["ftui l2","ftui l6"]'
                data-ptype='["lines","lines"]'
                data-uaxis='["primary","secondary"]'
                data-legend='["Temp", "Hum"]'
                data-yunit="°C"
                data-ytext="Temperatur"
                data-minvalue="auto"
                data-maxvalue="auto"
                data-yunit_sec="%"
                data-ytext_sec="Prozent"
                data-yticks="auto"
                data-minvalue_sec="auto"
                data-maxvalue_sec="auto"
                data-daysago_start="0"
                data-daysago_end="-1"
                data-crosshair="true"
                data-cursorgroup="1"
                data-scrollgroup="1"
                data-showlegend="true"
                data-xticks="auto"
                data-height="300px">
           </div>
   

          </li>
             
      </ul>
    </div>
</li>



Sorry wenn die Einrückungen jetzt nicht passen, aber bei mir wird das auf dem Server automatisch für die vorhandenen Devices zusammengebaut.

Hinweise zu Deinen Fehlern:
- Ein popup ist mit dem Slider eigentlich nicht nötig, oder willst Du den slider explizit in einm Popup anzeigen?
Ein popup im Slider macht aus meiner Sicht nicht unbedingt Sinn.
- Die Position der Punkte ist üblicherweise ausserhalb des Sliders, möglicherweise passen die Grössen nicht zusammen.
- Die Positionen lassen sich weiterhin auch mit den narrow-CSS-Elementen anpassen

Vorschlag zum Anfangen lege mal eine Slider mit ganz simplen Inhalt an (z.B: jeweils nur ein Label) und bau die Umschaltung mit Select+Dummy-Device. Dann von da aus erweitern um die richtigen Controls, wenn das stimmt die genaue Grössen aussen oder innen anpassen.

Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

FHEm2005

@ Viegener: Ich werde mal so vorgehen wie Du empfliehlst.

Ein erklärendes Wort zum Pop-up. In dem swiper-Fenster soll meine Squeezeboxsteuerung je Raum laufen. Das Pop-Up ist nur für die Vergrößerung des Cover-Bildes zuständig. Alles andere macht wirklich keinen Sinn. Aber das sich öffnende Fenster hat offensichtlich nicht die hohe Priorität (z-index), um vor dem Guckloch angezeigt werden zu können.

Gruß Eberhard.
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM, BSB-LAN

setstate

Dafür wartet schon ein Patch als pull Request im Github, glaube ich.  Ich schaue gleich mal nach ...

FHEm2005

@Viegener:
Ich habe mal das Grundgerüst nach Deinem Vorbild nachgebaut. Eine Frage: Die Select-Box oben dient zur Auswahl des Fensters, oder hat die andere Zwecke? Über die select-Box ein bestimmtes Item (von dreien) anzuspringen, klappt nicht. Ich verstehe auch nicht, warum das Device ftuiSelectSensor da ist?

Ich habe mal Deinen modifizierten Code mitgeliefert.  Ich habe aber nur den <body>-Teil beigefügt. Meine widget_Base_width und ~height ist jeweils "60". Du dürftest nur eine weißen Rahmen sehen, in dem ein Name steht.

<body>

<div class="gridster">
<ul>
<!-- Content -->
<div class="container">
<li data-row="1" data-col="1" data-sizex="9" data-sizey="8">


    <header>SB-Player</header>
<div class="cell wider inline">
          <div data-type="label" class="inline wider"></div>
          <div data-type="select" data-device="ftuiSelectSensor"
                    data-alias='["Küche","Wohnen","Büro"]'
                    data-items='["sb_Ku","sb_Wz","sb_Bu"]'
                    data-get="copyState" data-set="" class="w3x" ></div>
          <div></div>
    </div>


    <div data-type="swiper" data-height="350px" data-width="536px" data-get="copyState" data-device="ftuiSelectSensor"
         data-states='["sb_Ku","sb_Wz","sb_Bu"]'
         class="noswipe">
      <ul>
          <li data-hash="sb_Ku">
            <div
style= "width: 482px;
height: 275px;
border: 1px solid;
position:absolute;
top:31px;
left:26px;
margin: 0px;
background-image: url('images/squeezebox/wallpaper/fab4_sonata.png');" >
<div style = "font-size: 11px;
top: 219px;
left: 429px;
position: absolute;">Küche
</div>
</div>
          </li>

         <li data-hash="sb_Wz">
<div style= "width: 482px;
height: 275px;
border: 1px solid;
position:absolute;
top:31px;
left:26px;
margin: 0px;
background-image: url('images/squeezebox/wallpaper/fab4_sonata.png');" >
<div
style = "font-size: 11px;
top: 219px;
left: 429px;
position: absolute;">RX-V477
</div>
</div>             
        </li>

        <li data-hash="sb_Bu">
<div
style= "width: 482px;
height: 275px;
border: 1px solid;
position:absolute;
top:31px;
left:26px;
margin: 0px;
background-image: url('images/squeezebox/wallpaper/fab4_sonata.png');" >
<div style = "font-size: 11px;
top: 219px;
left: 429px;
position: absolute;">PC-Buero
</div>
</div>             
</li>       
      </ul>
    </div>
</li>
</div>
</ul>
</div>
</body>

Geht es überhaupt, ein Gerät über select auszuwählen, welches dann im Swiper angezeigt wird?

Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM, BSB-LAN

viegener

#14
Vielleicht nochmal generell zur Erklärung:

Es gibt keine direkte Verbindung zwischen dem select und dem swiper. Diese Verbindung findet über fhem statt und zwar mit dem dummy ftuiSelectSensor.

Ablauf:
1) Wenn man im Select einen neuen Wert einstellt, wird der state des dummy devices  ftuiSelectSensor in fhem auf diesen Wert gesetzt.
2) In dem device habe ich ein userReading copyState, dass nur den Wert des Readings state kopiert
  copyState { ReadingsVal("ftuiSelectSensor","state","");; }
3) Der geänderte copyState kommt wiederum in FTUI als Ereignis an
4) Die Änderung triggert eine Änderung des angezeigten Teiles im swiper (der ja auf denselben device/reading eingestellt ist)
(Das passiert indem der neue Wert mit dem Feld von Werten in data-states verglichen wird und der entsprechende index im Feld für das n-te Swiper-Element steht.

Den copyState habe ich eingeführt, da die Auswahl im select nicht immer ein update im swiper triggert und die Einführung eines getrennten Readings das zumindest verbessert hat
Ich denke da gibt es noch einen Fehler im FTUI --> Das führt dazu, dass (bei mir ?) die ersten 2-3 Selektionen nicht funktionieren, da wohl die Events noch nicht durchkommen?

Dem dummy ist es übrigens völlig egal welche texte im state stehen, ob das devicenamen oder Gemüsenamen sind ist irrelevant, da ein dummy ja wie der Name schon sagt weniger intelligent ist  ;)


Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können