Slider to JS variable
Alois
- html
- javascript
0 Rolf B0 Robert B.0 Der Martin0 Rolf B
0 Felix Riesterer0 Rolf B0 Felix Riesterer
-1 Alois
Hi all, Mein Problem: Ich versuche einen Slider-Wert in ein JS-Variable (strOut[0]) zu bringen, um den Wert dort weiter zu verarbeiten .... aber das geling nicht. Ich bitte um Hilfe!
<!DOCTYPE html>
<html>
<body>
<h2>Slider to JS-Var</h2>
<label id=Xout></label><label id=Xout2></label>
<br><br><br>
<strong>
<lable>Fußpunkt:</lable>
<lable><input type="range" id="fpIn" min="-20" max="0" value="-12"><span>0</span></lable>
<label> °C</lable>
<script>
const strOut=[];
var sliderFp = document.querySelector("input[type='range'][id='fpIn']");
sliderFp.addEventListener("change", function(){
document.querySelector("span").innerHTML = this.value;
strOut[0]=this.value;
document.getElementById("test1").innerHTML=strOut[0];
});
document.getElementById("Xout").innerHTML=">>> ";
document.getElementById("Xout2").innerHTML=strOut[0];
</script>
</body>
</html>
Hallo Alois,
Die Zuweisung an strOut[0] funktioniert prima.
Was nicht funktioniert - was Du erkennen würdest, wenn Du mal die Entwicklerwerkzeuge des Browsers aufmachst, einen Breakpoint bei der Zuweisung setzt und dann schrittweise weiterläufst - ist die Zuweisung an das innerHTML eines Elements mit der ID test2. Denn dieses Element gibt's nicht.
Damit möchtest Du an die Eigenschaft innerHTML von null
etwas zuweisen, und das bricht dein Script ab.
Wenn es Dir darum geht, dass beim ersten Aufruf der Seite die Zuweisung von strOut[0] an das Xout2 Element keinen Effekt hat - das liegt daran, dass zu diesem Zeitpunkt noch nichts an strOut[0] zugewiesen ist. Das passiert erst, wenn das erste change-Element ausgelöst wird. D.h. du musst beim Seitenstart - außerhalb des Eventhandlers - den Sliderwert einmalig ins Ausgabeelement übertragen.
Weitere Hinweise:
document.querySelector("input[type='range'][id='fpIn']")
- kann man machen, ist aber unnötig kompliziert. Eine ID muss im HTML Dokument eindeutig sein, und deshalb kannst Du hier auch document.querySelector("#fpIn")
oder document.getElementById("fpIn")
verwenden. Achte auf die Verwendung des # Zeichens. In querySelector muss es hinein, weil dort ein CSS Selektor verwendet wird und darin werden IDs mit einem # markiert.Als Minimalbeispiel würde ich das so bauen:
<!DOCTYPE html>
<html>
<head>
<style>
label[for=fpIn] {
font-weight:bold;
}
</style>
</head>
<body>
<h1>Slider to JS-Var</h1>
<div>
<label for="fpIn">Fußpunkt:</label>
<input type="range" id="fpIn" min="-20" max="0" value="-12">
<output aria-hidden="true">0</output> °C
</div>
<script>
const sliderFp = document.querySelector("#fpIn");
const sliderOut = document.querySelector("#fpIn + output");
sliderFp.addEventListener("input", function() {
sliderOut.textContent = sliderFp.value;
});
sliderOut.textContent = sliderFp.value;
</script>
</body>
</html>
#fpIn + output
findet ein output-Element, das direkt auf ein Element mit ID fpIn folgt.Rolf
Hallo Rolf, vielen Dank! Da kann ein Anfänger richtig was lernen .... toll! Leider löst es mein zentrales Problem nicht. Ich habe deinen eleganten code mal genommen und ein paar Zeilen eingefügt, da müsste man das eigentlich gut sehen können: Innerhalb der Funktion hält strOut[0] den Sliderwert, außerhalb geht die Variable wieder auf "undefined". Ich brauche aber den Wert außerhalb um mit ihm einen String zu konstruieren, den ich an meinen kleinen Web-Server schicken will. Anmerkung: Die Anzeige in dieser HTML-Seite ist NUR zur Demo hier und nicht mein Ziel. Ich brauche den Wert des Sliders auch nur nachdem er bewegt wurde.
<!DOCTYPE html>
<html>
<head>
<style>
label[for=fpIn] {
font-weight:bold;
}
</style>
</head>
<body>
<h1>Slider to JS-Var</h1>
<div>
<label for="fpIn">Fußpunkt:</label>
<input type="range" id="fpIn" min="-20" max="0" value="-12">
<output aria-hidden="true">0</output> °C
<p id="test1"></p>
<p id="test2"></p>
</div>
<script>
const strOut=[];
const sliderFp = document.querySelector("#fpIn");
const sliderOut = document.querySelector("#fpIn + output");
sliderFp.addEventListener("input", function() {
sliderOut.textContent = sliderFp.value;
strOut[0]=sliderFp.value;
document.getElementById("test1").innerHTML=strOut[0];
});
sliderOut.textContent = sliderFp.value;
document.getElementById("test2").innerHTML=strOut[0];
</script>
</body>
</html>
Hallo Alois,
du verstehst scheinbar das Konzept der Events noch nicht.
Das Script, so wie Du es jetzt hast, tut dies:
Zeilen 1 - 3: Deklaration von drei "Konstanten" - also letztlich Variablen, deren Wert Du nachher nicht mehr ändern kannst. Dieses "const" bezieht sich aber nur auf den Wert der Variablen selbst. Die "Werte" in diesen Variablen sind Objekte (strOut ist ein Array und die slider...-Variablen sind Verweise auf DOM Elemente), und diese Objekte werden durch das "const" nicht vor Veränderungen geschützt.
strOut ist jetzt ein leeres Array, d.h. strOut[0] ergibt den Wert undefined
.
Zeilen 5-9: Registrieren einer Funktion als EventListener für das input Event auf dem Slider. Hier passiert nichts außer dem Hinterlegen dieser Funktion als EventListener. Sie wird noch nicht ausgeführt.
Zeile 11: Auslesen von sliderFp.value, Speichern im textContent von sliderOut
strOut ist immer noch ein leeres Array
Zeile 12: Speichern von strOut[0] im innerHTML von #test2.
Was schrieb ich vorhin? innerHTML ist hier falsch. Es muss textContent sein. Du speicherst Text. Kein HTML.
NUN endet dein Script erstmal, und JETZT erst fängt der Browser an, die Seite darzustellen.
Sobald Du mit der Maus am Slider herumspielst, fängt er an, Events zu feuern. Jetzt wird die hinterlegte Funktion aufgerufen und speichert einen Wert in strOut[0]. Das hat aber für die Zeile 12 keine Bedeutung. Diese wird nicht mehr ausgeführt.
Ich brauche aber den Wert außerhalb um mit ihm einen String zu konstruieren, den ich an meinen kleinen Web-Server schicken will.
Die entscheidende Frage ist nun: Was soll diesen Abschickvorgang auslösen? Durch einen Timer? Einen Button? Soll der Wert automatisch nach dem Verändern des Sliders hochgeschickt werden?
Rolf
Ich will die Werte mehrerer Slider in einem String zusammen fassen und an den Server schicken. Es geht um das "Zusammenfassen". Es soll eine Strings entstehen, den ich dann an den Server schicken will. Dieses geht aber nur, wenn ich die Werte verfügbar habe. Das Abschicken an den Server ist implementiert und funktioniert prima.
Das Hochschicken wird mit einem manuel ausgelösten Button "Submit" getriggert. Wie gesagt, wenn ich den String haben funktioniert das bereits.
Hallo Rolf, das ist ja ganz vertrackt: Innerhalb eines "addEventListener" behält eine Vaiable ihren zugewiesenen Wert, außerhalb ist er weg. Das gilt auch für globale Variable. In deinem, von mir modifizierten Code, sieht man das ganz deutlich. Irgend eine Idee, den Slider-Wert da rauß zu bekommen?
<head>
<meta charset="UTF-8">
<style>
label[for=fpIn] {
font-weight:bold;
}
</style>
</head>
<body>
<h1>Slider to JS-Var</h1>
<div>
<label for="fpIn">Fußpunkt:</label>
<input type="range" id="fpIn" min="-20" max="0" value="-12">
<output aria-hidden="true">0</output> °C
</div>
<br><br>
<p id="test1">test1:</p>
<p id="test2">test2:</p>
<p id="test3">test3:</p>
<script>
const strOut=[];
window.addEventListener("change", function(){
const sliderFp = document.querySelector("#fpIn");
const sliderOut = document.querySelector("#fpIn + output");
sliderFp.addEventListener("input", function() {
sliderOut.textContent = sliderFp.value;
strOut[0]=sliderFp.value;
document.getElementById("test1").innerHTML=strOut[0];});
sliderOut.textContent = sliderFp.value;
document.getElementById("test2").innerHTML=strOut[0];
strOut[1]="yxz"
});
document.getElementById("test3").innerHTML=strOut[1];
</script>
</body>
</html>
Hallo,
könntest du bitte Code-Snippets auch als Code markieren, damit es besser lesbar ist? Also markieren, dann den Button </> über dem Eingabefeld drücken, und im besten Fall nach dem einleitenden ~~~ noch die Sprache notieren (z.B. html)?
Ich habe das mal für dich nachgeholt.
Einen schönen Tag noch
Martin
Hallo Alois,
wir erreichen nun das Thema "Scope von Variablen". Der Scope ist der Code-Bereich, wo eine Variable sichtbar ist.
Du hast strOut auf globaler Ebene definiert. Damit ist sie überall sichtbar und Werte, die Du im change- oder input-Handler des Sliders zuweist, sind auch in einem submit-Eventhandler sichtbar.
Aber: Was dein Beispiel zeigt, ist das, was ich schon vorher einmal erklärt habe: Die Eventhandler-Funktion wird von addEventListener lediglich registriert, aber nicht ausgeführt. Dein Code läuft nicht linear von oben nach unten. Die EventListener-Funktion wird erst später aufgerufen, wenn sich der Wert des Sliders ändert. Und dann läuft nur die Funktion und sonst nichts. Deine Ausgabe von strOut[1] am Ende findet statt, bevor die Funktion das erste Mal läuft.
Und Du machst andere Dinge falsch.
Schau erstmal hier: Grundlagen der Ereignisverarbeitung, vor allem das Thema "Bubbling".
Du registrierst einen change-Handler auf dem window Objekt. Das hast Du bisher nicht getan, warum jetzt? Das change-Event gelangt natürlich irgendwann per Bubbling dorthin, aber es ist nicht so einfach, ein change- oder input-Event zu verarbeiten, das hochgebubbelt ist. Gerade dann nicht, wenn Du, wie hier, den Wert eines Sliders als Klartext anzeigen willst und Du mehrere Slider hast. Jeder Slider kann change auslösen, und diese change Events würden alle im gleichen Eventhandler landen. Es ist möglich, so vorzugehen, aber nicht so einfach.
Du registrierst innerhalb dieses change-Handlers einen input-Handler. Das ist ganz falsch, weil Du dann bei jedem change-Event einen neuen input-Handler hinzufügst.
Wenn Du die Slider zusammen mit dem Submit-Button in ein <form> Element packst, dann kannst Du über einen submit-Handler den Submit auf einen XMLHttpRequest umlenken (oder machst es mit jQuery Ajax oder dem fetch-API) und den Form-Inhalt über ein FormData Objekt an den Server posten. Es ist dann überhaupt nicht nötig, sich die Slider-Werte im change- oder input-Event zu merken. Guck Dir hier mal Beispiel 2 an, um zu sehen, wie man aus dem Form-Element das FormData Objekt erzeugt und via XMLHttpRequest verschickt.
Rolf
Hallo Rolf, zu 1. und 2. : Ich hatte das einfach aus einem Beispiel übernommen. War eher ein verzweifelter Versuch. Zu 3. : Das schau ich mir jetzt mal an.
Auf alle Fälle erstmal vielen Dank für deine Hinweise (...und deine Geduld)!
Grüße Alois
Moin Alois,
<!DOCTYPE html> <html>
Das Gradzeichen °
ist außerhalb des ASCII-Zeichensatzes, weshalb es sinnvoll sein kann, im head
die Codierung deines Dokuments anzugeben. Default ist in HTML ISO-8859-1.
<body> <h2>Slider to JS-Var</h2> <label id=Xout></label><label id=Xout2></label>
Die Hauptüberschrift eines Dokuments sollte immer h1
sein und label
ohne zugeordnete Formularelemente wirken auf mich falsch (siehe auch https://wiki.selfhtml.org/wiki/HTML/Elemente/label).
<br><br><br>
Zeilenumbrüche sind keine Spacing-Elemente.
<strong>
Das strong
hat kein End-Tag und umschließt auch das Input.
<lable>Fußpunkt:</lable> <lable><input type="range" id="fpIn" min="-20" max="0" value="-12"><span>0</span></lable> <label> °C</lable>
Das Element heißt label
und nicht lable
und beschreibt das Formularelement – so wie Rolf vorgeschlagen hat – oder in der Form
<label>Fußpunkt:
<input type="range" id="fpIn" min="-20" max="0" value="-12">
<output aria-hidden="true"></output> °C
</label>
Das Zeichen mit dem Unicode-Point 202f
ist ein schmales geschütztes Leerzeichen, wie es zwischen Zahlen und Einheiten verwendet wird.
const strOut=[]; var sliderFp = document.querySelector("input[type='range'][id='fpIn']");
Das Objekt kann doch auch const
sein – und es wird ziemlich kompliziert ermittelt: "#fpIn"
sollte vollkommen ausreichen, da die ID eindeutig sein muss, es darf also keine weiteren Elemente mit dieser ID geben.
sliderFp.addEventListener("change", function(){ document.querySelector("span").innerHTML = this.value; strOut[0]=this.value; document.getElementById("test1").innerHTML=strOut[0]; });
Neben dem change
-Event träfe auch das input
-Event zu. Aber das eigentliche Problem an der Stelle ist, dass es kein Element mit der ID test1
gibt. (Und getElementById
kannst du natürlich auch anstelle von querySelector("#…")
verwenden.)
document.getElementById("Xout").innerHTML=">>> ";
document.getElementById("Xout2").innerHTML=strOut[0];
Das steht außerhalb des Event-Handlers, wird also nur einmal beim Abarbeiten des JavaScript-Codes ausgeführt. Und nach meinem Verständnis sollte man innerHTML
gültigen HTML-Code zuweisen, dafür müsstest du doch die spitzen Klammern kontextgerecht behandeln. Aber in deinem Fall reichte auch die textContent
-Eigenschaft vollkommen aus.
Viele Grüße
Robert
Hallo Robert,
Das Gradzeichen
°
ist außerhalb des ASCII-Zeichensatzes, weshalb es sinnvoll sein kann, imhead
die Codierung deines Dokuments anzugeben. Default ist in HTML ISO-8859-1.
da wäre das Grad-Zeichen enthalten. Trotzdem ist es eine gute Idee, die verwendete Codierung explizit anzugeben. Bevorzugt im HTTP-Header, aber eine Angabe per meta-Element im Dokument ist als Fallback auch kein Fehler.
Das Zeichen mit dem Unicode-Point
202f
ist ein schmales geschütztes Leerzeichen, wie es zwischen Zahlen und Einheiten verwendet wird.
Außer bei Einheiten, die nicht mit Buchstaben notiert werden wie Grad oder Prozent - die werden ohne Abstand direkt an den Zahlenwert gehängt.
Zumindest habe ich das so gelernt.
Einen schönen Tag noch
Martin
Trotzdem ist es eine gute Idee, die verwendete Codierung explizit anzugeben. Bevorzugt im HTTP-Header, aber eine Angabe per meta-Element im Dokument ist als Fallback auch kein Fehler.
Mehr noch als "kein Fehler". Es ist eine gute Idee, die Codierung im Header und im Markup anzugeben. Die Angabe im Markup wirkt auf den ersten Blick vielleicht obsolet, wenn sie doch schon im Header vorgenommen hat.
Was aber, wenn es gar keinen Header gibt, weil ich beispielsweise eine Seite lokal gespeichert habe? Dann ist die Meta-Angabe sehr nützlich.
Hallo Robert B.,
weshalb es sinnvoll sein kann, im head die Codierung deines Dokuments anzugeben. Default ist in HTML ISO-8859-1.
Und das ist total bekloppt, denn: https://html.spec.whatwg.org/#charset
Danach kennt HTML 5 nur noch UTF-8, dieses Encoding ist für HTML-5 Dokumente verpflichtend.
Mein Chrome hier führt beim Laden von file:/// ein character sniffing durch und unterscheidet automatisch zwischen windows-1252 (was nicht ganz iso-8859-1 ist) und utf-8. Ich habe gerade keinen Webserver unter den Fingern, keine Ahnung ob er sich da anders verhält.
Also grundsätzlich: Ja, man sollte <meta charset="utf-8"> hinschreiben und seine HTML Dateien auch so speichern. Das spart eine Menge Ärger.
Rolf
Lieber Alois,
Mein Problem: Ich versuche einen Slider-Wert in ein JS-Variable (strOut[0]) zu bringen, um den Wert dort weiter zu verarbeiten ...
nein, das ist nicht Dein Problem. Diese Deine Worte sind die sprichwörtliche „Story vom Pferd“, denn was Du wirklich zu lösen versuchst, ist in der Tat etwas ganz anderes:
Ich will die Werte mehrerer Slider in einem String zusammen fassen und an den Server schicken.
Also! Dann lass uns doch genau darüber reden, und nicht über Deine konfuse Beschreibung eines Detailproblems, das auf einer falschen Grundannahme beruht.
Du willst einen Button manuell auslösen, um den aktuellen Zustand von allen Deinen Slidern in Form eines Strings zusammenzufassen. Dazu registrierst Du einen EventListener auf genau diesem Button:
<p><button id="update-server">Sliderzustände an Server melden</button></p>
<script>...</script>
In das Script kommt nun folgendes:
document
.getElementById("update-server")
.addEventListener(
"click",
event => {
let myString = [];
// alle Slider finden
document
.querySelectorAll('input[type="range"]')
.forEach(slider => {
// String mit Slider-Wert erweitern
myString.push(slider.name + "=" + slider.value);
});
// POSTe alle Teilstrings in `myString` an den Server
}
);
Die EventListener für Änderungen an den Slidern haben mit Deinem an-den-Server-senden nichts zu tun. Sie zeigen nur den jeweiligen Slider-Wert in einem passenden HTML-Element an, damit man das genauer sehen kann. Konzentrieren wir uns also besser überhaupt nicht darauf, sondern nur auf das Auslesen von allen Slidern auf einen Knopfdruck hin.
Zum besseren Verständnis des Codes:
variable => { ... }
ist eine modernere Schreibweise für function (variable) { ... }
(siehe auch Pfeilfunktion)type
-Attribut) auszuwählen, verwendet man die document
-Methode querySelector
. Will man alle Elemente mit dieser Eigenschaft erhalten, verwendet man document.querySelectorAll
. Als Parameter übergibt man einen Selektor, wie er auch bei CSS verwendet wird.forEach
-Methode ist nicht nur bei Array-Objekten verfügbar, sondern auch bei dem Objekt, welches von document.querySelectorAll
zurückgegeben wird. Damit kann man die gefundenen HTML-Elemente der Reihe nach ansprechen. Dazu will forEach
aber eine Funktion als Parameter haben, in der geregelt wird, wie mit dem jeweiligen Element (hier in der Variable slider
übergeben) verfahren werden soll.Liebe Grüße
Felix Riesterer
Hallo Felix,
neue JS Features wie Pfeilfunktionen sollten wir außen vor lassen, es ist für Alois schon genug an neuem Wissen, denke ich.
Ist es nicht einfacher, die Slider - und was sonst zum Versand ansteht - in ein Form zu stecken und aus dem Form ein FormData zu initialisieren? Form und PHP sollten so gebaut sein, dass ein POST des Forms ebenfalls funktioniert, als Fallback falls das JS nicht ausgeführt wird. Mit JS verwendet man einen submit Listener.
Gerade entdeckt: Ein FormData Objekt kann verwendet werden, um ein URLSearchParams-Objekt zu initialisieren. Auf dem ruft man toString() auf und verwendet es als Body für den POST Request.
<form name="temperaturen" method="POST" action="setTemp.php">
<label for...>...</label><input type="range" name="temp1" min... max...>
<label for...>...</label><input type="range" name="temp2" min... max...>
<label for...>...</label><input type="range" name="temp3" min... max...>
<button name="save" value="form">Senden</button>
</form>
Die Labels sind nur angedeutet und müssen natürlich ausformuliert werden.
document.forms.temperaturen.addEventListener("submit", function(submitEvent) {
const params = new URLSearchParams(new FormData(submitEvent.target));
params.set("save", "ajax");
// hier Ajax-Code, versende damit params.toString() an setTemp.php
// zum Beispiel:
fetch("setTemp.php", {
method: "POST",
body: params.toString(),
headers: { "Content-Type", "application/x-www-form-urlencoded" });
// Submit durch den Browser verhindern
submitEvent.preventDefault();
});
submitEvent.target ist das Form-Element, daraus wird ein FormData und daraus ein URLSearchParams Objekt. Der save-Button ist darin nicht enthalten, das passiert nur beim Browser-Versand. Deshalb wird der save-Eintrag gefaked, mit einem vom Form abweichenden Value, so dass man ggf. am Server zwischen einem POST durch den Browser und einen POST durch den EventListener unterscheiden kann.
Dann folgt Standard-AJAX-Code, XMLHttpRequest oder fetch, zum Hochschicken. Darin muss man den Content-Type Header auf application/x-www-form-urlencoded setzen.
Statt den Header zu setzen kann man auch auf die Einkapselung in URLSearchParams verzichten und direkt das FormData Objekt schicken, das geschieht dann aber automatisch als multipart/form-data. Das ist PHP egal, sind aber mehr Bytes auf der Leitung.
Fertig. Ein Merken der Sliderwerte im change-Handler ist in keinem Fall nötig.
Rolf
Lieber Rolf,
neue JS Features wie Pfeilfunktionen sollten wir außen vor lassen, es ist für Alois schon genug an neuem Wissen, denke ich.
wenn Du meinst, dass die Schreibweise ein Problem sein sollte... das kann nur Alois beantworten.
Ist es nicht einfacher, die Slider - und was sonst zum Versand ansteht - in ein Form zu stecken und aus dem Form ein FormData zu initialisieren?
Für Alois war genau dieses Problem laut seinen Worten schon gelöst. Er bastelt einen wie auch immer gearteten String und schickt ihn irgendwie an den Server. Ob das aber besser mit FormData und Ajax passieren sollte, und ob das Formular unbedingt auch über einen regulären POST-Request an den Server übertragen werden können muss - weil das als Default/Fallback das technische Minimum bedeutet und JS lediglich als progressive enhancement fungieren darf - erscheint mir das Alois' Formulierungen nach entweder für ihn fremd, oder für seinen (uns unbekannten) Anwendungsfall bewusst gewählt.
Liebe Grüße
Felix Riesterer
Hallo Felix Riesterer,
wenn Du meinst, dass die Schreibweise ein Problem sein sollte
Pfeilfunktionen unterscheiden sich auch bezüglich this
. Für jemanden, der offenbar noch mit Eventverarbeitung und Scoping kämpft, ein Zukunftsthema. Find ich.
Mein Plädoyer für ein Form und Formdata bezieht sich hauptsächlich auf das Einsparen von selbst zu schreibendem (und zu testendem) Code und eine sinnvolle Seitengestaltung.
Rolf
Hallo Felix ... genauso ist das! Ich bin ziemlicher Leie was HTML/JS/PHP .... betrifft und will auch kein Könner werden. Was ich mache: Ich baue mir mit einem ESP32 eine Heizungssteuerung (Wärmepumpe) und das wird auch funktionieren. Statt einer Eingabe über Druckknöpfe und eine LCD-Ausgabe will das gerne über mein Handy machen und das läuft auch fast schon alles (wahrscheinlich ziemlich unelegant) bis auf die Geschichte mit den Slidern. Leider ist es immer noch so, dass ich die Werte nicht verfügbar bekommen. Für einen 3/4/5-Zeiler, der das macht wäre ich schon sehr dankbar!
Beste Grüße Alois
Lieber Alois,
Was ich mache: Ich baue mir mit einem ESP32 eine Heizungssteuerung (Wärmepumpe) und das wird auch funktionieren. Statt einer Eingabe über Druckknöpfe und eine LCD-Ausgabe will das gerne über mein Handy machen
jetzt haben wir endlich die ganze Geschichte!
und das läuft auch fast schon alles
Anscheinend nicht.
Leider ist es immer noch so, dass ich die Werte nicht verfügbar bekommen.
Eben.
Also hat Rolf schon Recht, wenn er vorschlägt, dass Du Dein Formular mit den Slidern ganz regulär abschickst, damit ihre Werte auf die übliche Weise beim Server ankommen. Damit ersparst Du Dir den Hickhack mit JavaScript.
Zeig mal, wie Dein Dokument wirklich aussieht (egal, ob auf Codepen, Dabblet oder JSFiddle, nur nicht hier in einer Code-Wurst). Dann kann man Dir auch helfen. Wenn Du es mit PHP zusammenbaust, dann zeige bitte nicht den PHP-Quelltext, sondern das Ergebnis in HTML. Wenn Du kein PHP verwendest, dann erzähle uns bitte auch, wie das HTML erzeugt wird.
Liebe Grüße
Felix Riesterer
Hallo Felix Riesterer,
ganz regulär abschickst
Als Fallback. Ein submit-Handler als progressive enhancement ist ja nicht verboten.
Aber ein Form ist auf jeden Fall eine hilfreiche Maßnahme.
Und selbst wenn Alois das nicht will - das Speichern in JavaScript-Variablen ist das falsche Konzept. Man lese beim Senden einfach die Slider neu aus.
Die bisher von Alois beschriebenen Probleme zeigen jedenfalls ein solides Unverständnis von Eventhandling, denn die Werte landen ja in den Variablen. Er gibt sie nur zu früh aus und wundert sich dann.
Rolf
So klappt das jetzt! Zur Demo sende ich Slider-Werte nicht an den Server sondern gebe sie auf der HTML-Seite aus. Den "Durchbruch" hat das Script-Teil //Slider to String gebracht!
Vielen Dank nochmal an alle Helfer und vorallem die GEDULD die ihr aufgebracht habt!
Grüße Alois
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
label {font-weight:bold;}
output {font-weight:bold;text-align: center;}
input {text-align: center;}
.slidecontainer {
width: 300px;
margin-left: auto !important;
margin-right: auto !important;}
</style>
</head>
<body>
<div class=slidecontainer>
<p><strong>Fußpunkt:<strong></p>
<input type="range" id="fpIn" min="-20" max="0" value="-15">
<output></output> °C <hr><br>
<p><strong>Steigung:<strong></p>
<input type="range" id="stIn" min="-.8" max="-.2" value="-0.5" step="0.01">
<output aria-hidden="true"></output> R/A<hr><br>
<p><strong>von Wind:<strong></p>
<input type="range" id="wiIn" min="0" max="6" value="2" step="0.5">
<output aria-hidden="true"></output> %<hr><br>
<p><strong>von Licht:<strong></p>
<input type="range" id="liIn" min="0" max="6" value="3" step="0.5">
<output aria-hidden="true"></output> %<hr><br>
<button id="update-server">Werte senden</button>
<output id=Out></output>
</div>
<script>
// Slider ---------------------------------------------------------
const sliderFp = document.querySelector("#fpIn");
const sliderFpOut = document.querySelector("#fpIn + output");
sliderFp.addEventListener("input", function() {
sliderFpOut.textContent = sliderFp.value; });
sliderFpOut.textContent = sliderFp.value;
const sliderSt = document.querySelector("#stIn");
const sliderStOut = document.querySelector("#stIn + output");
sliderSt.addEventListener("input", function() {
sliderStOut.textContent = sliderSt.value; });
sliderStOut.textContent = sliderSt.value;
const sliderWi = document.querySelector("#wiIn");
const sliderWiOut = document.querySelector("#wiIn + output");
sliderWi.addEventListener("input", function() {
sliderWiOut.textContent = sliderWi.value; });
sliderWiOut.textContent = sliderWi.value;
const sliderLi = document.querySelector("#liIn");
const sliderLiOut = document.querySelector("#liIn + output");
sliderLi.addEventListener("input", function() {
sliderLiOut.textContent = sliderLi.value; });
sliderLiOut.textContent = sliderLi.value;
//Slider to String ---------------------------------------------
document
.getElementById("update-server")
.addEventListener(
"click",
event => {
let myString = [];
// alle Slider finden
document
.querySelectorAll('input[type="range"]')
.forEach(slider => {
// String mit Slider-Wert erweitern
myString.push(slider.name + "&" + slider.value); });
// POSTe alle Teilstrings in `myString` an den Server
strOut = myString+"#";
document.getElementById("Out").innerHTML = strOut; });
</script>
</body>
</html>
Hallo Alois,
.forEach(slider => {
// String mit Slider-Wert erweitern
myString.push(slider.name + "&" + slider.value); });
strOut = myString+"#";
kann man machen. Aber das ist alles andere als Standard.
Dein 12 Monate älteres Ich, das diesen Code liest und seitdem mehr gelernt hat, wird Dich dafür HASSEN.
Vor allem, weil Du auf dem Server nun die Parameter in Eigenregie wieder auseinandernehmen musst.
Vorschlag:
const url = new URL("http://mein-esp32/set_temp.php");
document
.querySelectorAll('input[type="range"]')
.forEach(slider => {
// URL mit Slider-Wert erweitern
url.searchParams.append(slider.name, slider.value);
});
document.getElementById("Out").textContent = url.toString(); });
Damit bekommst Du eine fertige URL, wo die Parameter als URL Parameter drinstehen. "mein-esp32" musst Du natürlich geeignet ändern.
Damit kannst Du einen POST-Request an deinen ESP32 machen (ja, POST, weil Du was änderst - ein GET Request ist hier falsch). Dass die Parameter in der URL statt im Body übergeben werden, ist erlaubt.
Also so:
const xhr = new XMLHttpRequest();
xhr.open("POST", url.toString());
xhr.send();
Oder als Einzeiler so:
fetch(url.toString(), { method: 'POST') });
Das .toString() kannst Du vermutlich sogar weglassen, ich kann es gerade nur nicht ausprobieren.
Im PHP findest Du dann in $_SERVER['REQUEST_METHOD'] den Wert 'POST' vor, um den Requesttyp zu erkennen, und im $_GET Array die übergebenen Daten. Wenn Du denn PHP auf dem ESR verwendest und nicht irgendwas anderes.
Rolf
Moin Alois,
wenn du Quellcode im Forum passend auszeichnest, hilft das ungemein beim Verstehen … Und ein paar Dinge sind weiterhin, obwohl du darauf hingewiesen worden bist.
label {font-weight:bold;}
Dein folgender HTML-Code enthält gar keine label
.
input {text-align: center;} .slidecontainer { width: 300px; margin-left: auto !important; margin-right: auto !important;}
Eine fixe Breite in Pixel kann beim Vergrößern/Verkleinern (Zoomen) der Seite problematisch angezeigt werden, nimm lieber relative Dimensionen.
<div class=slidecontainer>
… oder auch form
oder fieldset
.
<p><strong>Fußpunkt:<strong></p> <input type="range" id="fpIn" min="-20" max="0" value="-15"> <output></output> °C <hr><br>
Die label
hätte ich jetzt hier erwartet. Was die hr
-Trenner und vor allem der Zeilenumbruch vor dem nächsten Absatz sollen, ist mir unklar. Das br
brauchst du gar nicht, das hr
erscheint auch deplatziert.
Das betrifft natürlich die Konstrukte aller deiner Inputs.
<button id="update-server">Werte senden</button>
Ein button
ohne type
ist ein Submit-Button. Daran musst du bei der Verwendung von form
s denken.
Viele Grüße
Robert