• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

[GELOEST] slider change function für mehrere input slider...

chromo23

Neues Mitglied
Hallo,
ich bastele immer noch an meiner dynamisch generierten Seite für eine microcontroller firmware.
Hintergrund: https://www.html.de/threads/uebersicht-aus-json-generieren.60684/#post-407689
Dort hatte mir ja @Sempervivum schon sehr geholfen.

Nun habe ich diese Seite um Buttons und Slider erweitert. Wenn ein Gerät die phrase "slider" beinhaltet, dann wird ein ein Slider generiert:
Javascript:
 else if ((sensor.TaskName).toLowerCase().includes("slider")) {  //if a task contains "slider" it generates an input slider
  html2 += '<div class="sensorset">' + '<input type="range" min="0" max="1023" value="' + sliderValue + '" id="slider1" class="slider" onchange="updateSlider(this.value,\'' + utton + '\')" oninput="isitTime()">' + '<div  class="sensors" style="align-items: flex-end;"">' + '<div style="font-weight:bold;font-size: 14pt;">' + sensor.TaskName + '</div>' + '<div id="sliderAmount" style="text-align: right;">' + sliderValue + '</div>' + '</div>';
 }

Mit "onchange" wird eine Funktion gestartet, die die Daten dem Microcontroller übergibt (das funktioniert sehr gut):
Javascript:
<script>
    function isitTime() { //oninput of slider calls this function to prevent refereshing the page while sliding
        window.isittime = 0;
    }

    function updateSlider(slideAmount, utton) {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
            }
        }
        xhr.open('get', 'control?cmd=event,' + utton + 'event=' + slideAmount, true); //generating the event+values vor all the slider
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
        xhr.send();
        window.isittime = 1;
    }
</script>

Um die Werte direkt beim Sliden zu sehen benutze ich folgenden Script:
Wenn ich nur einen Slider habe funktioniert der Script auch sehr gut
Javascript:
<script>
    function sliderStart() {
        var slider = document.getElementById('slider1');
        slider.addEventListener('input', sliderChange);
    }
    function sliderChange() {

        var sliderDiv = document.getElementById("sliderAmount");
        sliderDiv.innerHTML = this.value;
        console.log(this.value);
    }
</script>
Habe ich mehrere slider geht das so natürlich nicht mehr.
Ich habe versucht nach dieser Anleitung vor zu gehen: https://stackoverflow.com/questions/48134220/javascript-updating-multiple-slider-innerhtml/48137573
Bin aber kläglich gescheitert. :oops:
Ich würde mich freuen wenn jemand mir helfen könnte.

demoslider.gif



Im Anhang der ganze Code als Kontext
 

Anhänge

  • html.zip
    3,8 KB · Aufrufe: 0
Zuletzt bearbeitet:

Sempervivum

Senior HTML'ler
Wenn ich das richtig sehe, sieht dein HTML so aus:
Code:
    <div class="sensorset">
        <input type="range" min="0" max="1023" value="50" id="slider1" class="slider"
            onchange="updateSlider(this)"
            oninput="isitTime()">
        <div class="sensors" style="align-items: flex-end;">
            <div style=" font-weight:bold;font-size: 14pt;">taskname</div>
            <div class="sliderAmount" style="text-align: right;">50</div>
        </div>
    </div>
und Du möchtest den aktuellen Wert des Sliders in das div.sliderAmount eintragen. Das würde dann mit diesem Javascript gehen:
Code:
    <script>
        function updateSlider(slider) {
            // div.sliderAmount ausgehend vom Slider ermitteln:
            // Zunächst nach oben das div.sensorset finden
            // und dann nach unten das div.sliderAmount:
            const amount = elem.closest('div.sensorset').querySelector('.sliderAmount');
            // Text im div.sliderAmount auf den aktuellen Wert des Sliders setzen:
            amount.textContent = slider.value;
        }
        function isitTime() { }
    </script>
Falls Du auch noch solch einen Balken haben möchtest, kannst Du versuchen, ihn selber hinzuzufügen.
 

chromo23

Neues Mitglied
Danke für deine Antwort, aber ich glaube du hast mich missverstanden .
Die Funktion updateSlider funktioniert wie sie soll für alle Slider (die werden ja je nach gerät dynamisch hinzugefügt). Und auch die Funktion sliderChange funktioniert wie sie soll für einen Slider. Wie auf dem Gif zu sehen.
Ist deine Lösung nicht nur eine andere Vorgehensweise für das was ohnehin schon funktioniert? (Sorry, wenn das ne doofe Frage ist aber ich steh bei Javascript echt aufm Schlauch)

Hier wird ja ne Variable (utton) übergeben, die für jeden Slider, der generiert wird, eindeutig ist
CSS:
onchange="updateSlider(this.value,\'' + utton + '\')"
Hier wird sie übergeben:
Javascript:
   function updateSlider(slideAmount, utton) {
Ich hatte auch schon anhand dieser Funktion die Werte für alle Slider erfolgreich ausgeben.
Das Problem bei onchange ist halt nur onchange und nicht während ich den slider bewege (nur wenn ich ihn loslasse)

Desahlb habe ich das hiermit zu lösen versucht:
Javascript:
    slider.addEventListener('input', sliderChange);
Aber dass muss ich nur noch variabel gestalten, da ja die Anzahl der Slider variieren
Der Link im ersten Post ist glaub ich ein guter Ansatz bei dem ich nur noch nicht durchblicke.
 

Sempervivum

Senior HTML'ler
Ich hatte mein Augenmerk auf dieses gerichtet:
Habe ich mehrere slider geht das so natürlich nicht mehr.
und den Code so geändert, dass er für beliebig viele Slider funktioniert. Leider ist mir dabei ein Fehler unterlaufen indem ich elem statt slider geschrieben habe. Dieses funktioniert jetzt bei mir:
Code:
    <div class="sensorset">
        <input type="range" min="0" max="1023" value="50" id="slider1" class="slider" onchange="updateSlider(this)"
            oninput="isitTime()">
        <div class="sensors" style="align-items: flex-end;">
            <div style=" font-weight:bold;font-size: 14pt;">taskname</div>
            <div class="sliderAmount" style="text-align: right;">50</div>
        </div>
    </div>
    <div class="sensorset">
        <input type="range" min="0" max="1023" value="50" id="slider2" class="slider" onchange="updateSlider(this)"
            oninput="isitTime()">
        <div class="sensors" style="align-items: flex-end;">
            <div style=" font-weight:bold;font-size: 14pt;">taskname</div>
            <div class="sliderAmount" style="text-align: right;">50</div>
        </div>
    </div>
    <div class="sensorset">
        <input type="range" min="0" max="1023" value="50" id="slider3" class="slider" onchange="updateSlider(this)"
            oninput="isitTime()">
        <div class="sensors" style="align-items: flex-end;">
            <div style=" font-weight:bold;font-size: 14pt;">taskname</div>
            <div class="sliderAmount" style="text-align: right;">50</div>
        </div>
    </div>
    <script>
        function updateSlider(slider) {
            // div.sliderAmount ausgehend vom Slider ermitteln:
            // Zunächst nach oben das div.sensorset finden
            // und dann nach unten das div.sliderAmount:
            const amount = slider.closest('div.sensorset').querySelector('.sliderAmount');
            // Text im div.sliderAmount auf den aktuellen Wert des Sliders setzen:
            amount.textContent = slider.value;
        }
        function isitTime() { }
    </script>
Dabei ermittelt diese Zeile:
Code:
const amount = slider.closest('div.sensorset').querySelector('.sliderAmount');
das div.sliderAmount, das zu dem aktuellen Slider gehört.

Natürlich kannst Du die Eventlistener auch mit addEventlistener registrieren.
 
Zuletzt bearbeitet:

chromo23

Neues Mitglied
Dein Beispiel funktioniert sehr gut aber leider ist diese Lösung keine Option, da wie ja schon geschrieben, Werte nur nach loslassen des Sliders aktualisiert werden. ("onchange" eben)
Was ich meine siehst du im ersten Post im Gif. Dort verändert der obere Slider seine Werte kontinuierlich.
Die updateSlider Funktion nutze ich zwar auch aber nur, dass nach "loslassen" des Sliders die Werte an den Microcontroller übergeben werden. (Der wäre überfordert mit der kontinuierlichen Fütterung von Daten)

Hier kannst du schauen wie ich das meine: https://jsfiddle.net/0fzxpsdt/1/
Der erste Slider wird im diesen Beispiel angesprochen.
Ich denke ich muss dafür multiple Eventlistner aufrufen.
 

Sempervivum

Senior HTML'ler
Ah so, das meinst Du. Dann brauchst Du allerdings zwei Eventlistener, einen für "input" und einen für "change". Den für "input" hast Du ja schon, da brauchst Du nur noch das sliderChange() dranzuhängen:
Code:
    <input type="range" min="0" max="1023" value="431" id="slider1" class="slider"
        onchange="updateSlider(this.value,'slider1')" oninput="isitTime();sliderChange();">
 

chromo23

Neues Mitglied
Funktioniert! aber nur bedingt.
da sliderChange ja den Eventlistener erst aufruft, wenn der Slider schon Aktiv ist. Beim kontinuierlichen Sliden fällt das fast nicht auf. Aber wenn ich irgendwo in den Sliderbereich klicke, dann sieht das erste Ergebnis verständlicherweise so aus:
sliderundef.png
 

chromo23

Neues Mitglied
Soweit bin ich schon gekommen. Ich generiere ein Array aus allen Slidern und generiere daraus Eventlistener:

CSS:
var sliderList = document.getElementsByTagName('input');
var sliderArray = [].map.call(sliderList, function(el) {
  return el.id;
});
call_me(sliderArray);

function call_me(params) {
  for (i=0; i<params.length; i++) {
   var slider = document.getElementById(params[i]);
slider.addEventListener('input', sliderChange);

  }
}
function sliderChange() {

  var sliderDiv = document.getElementById("sliderAmount");
  sliderDiv.innerHTML = this.value;
  console.log(this.value);
}

Ich weiß nur noch nicht so recht wie ich das dann an sliderChange übergebe.....
 

Sempervivum

Senior HTML'ler
Das hast Du ja sehr kompliziert gemacht: Erst ein Array mit IDs ermitteln und dann wieder aus der ID das Element. Außerdem kann sliderChange so nicht funktionieren denn mit diesem:
Code:
var sliderDiv = document.getElementById("sliderAmount");
ermittelst Du ja immer das selbe sliderAmount-Element und nicht das, was zu den aktuellen Slider gehört.
Versuche es so und lies dir meine Kommentare genau durch:
Javascript:
        // Wir ermitteln zunächst eine Liste aller Slider:
        const sliders = document.querySelectorAll('input[type="range"]');
        // Fuer jeden einzelnen Slider registrieren wir zwei
        // Eventlistener mit der betr. Funktion als Callback:
        sliders.forEach(slider => {
            slider.addEventListener('input', updateSlider);
            slider.addEventListener('change', sliderChange);
        });
        function updateSlider(event) {
            // Den Slider, der das Event ausgelöst hat,
            // finden wir unter event.target:
            slider = event.target;
            // div.sliderAmount ausgehend vom Slider ermitteln:
            // Zunächst nach oben das div.sensorset finden
            // und dann nach unten das div.sliderAmount:
            const amount = slider.closest('div.sensorset').querySelector('.sliderAmount');
            // Text im div.sliderAmount auf den aktuellen Wert des Sliders setzen:
            amount.textContent = event.target.value;
        }
        function sliderChange(event) {
            // Den Slider, der das Event ausgelöst hat,
            // finden wir unter event.target:
            slider = event.target;
            // Hier weitere Aktionen mit dem Slider
            console.log('sliderChange called');

            // Offenbar muss ausserdem die Funktion isitTime
            // aufgerufen werden:
            isitTime();
        }
        function isitTime() {
            console.log('isitTime called');
        }
Die inline-Listener brauchst Du dann nicht mehr:
HTML:
    <div class="sensorset">
        <input type="range" min="0" max="1023" value="50" id="slider1" class="slider">
        <div class="sensors" style="align-items: flex-end;">
            <div style=" font-weight:bold;font-size: 14pt;">taskname</div>
            <div class="sliderAmount" style="text-align: right;">50</div>
        </div>
    </div>
    <div class="sensorset">
        <input type="range" min="0" max="1023" value="50" id="slider1" class="slider">
        <div class="sensors" style="align-items: flex-end;">
            <div style=" font-weight:bold;font-size: 14pt;">taskname</div>
            <div class="sliderAmount" style="text-align: right;">50</div>
        </div>
    </div>
    <div class="sensorset">
        <input type="range" min="0" max="1023" value="50" id="slider1" class="slider">
        <div class="sensors" style="align-items: flex-end;">
            <div style=" font-weight:bold;font-size: 14pt;">taskname</div>
            <div class="sliderAmount" style="text-align: right;">50</div>
        </div>
    </div>
 

chromo23

Neues Mitglied
Das hast Du ja sehr kompliziert gemacht: Erst ein Array mit IDs ermitteln und dann wieder aus der ID das Element. Außerdem kann sliderChange so nicht funktionieren denn mit diesem:
Willst du es mal richtig kompliziert sehen::wink:

HTML:
   <div class="sensorset"><input type="range" min="0" max="1023" value="456" id="slider" class="slider"
            onchange="updateSlider(this.value,'slider')" oninput="isitTime('slider','sliderAmount');sliderChange()">
        <div class="sensors" style="align-items: flex-end;">
            <div style="font-weight:bold;font-size: 14pt;">slider</div>
            <div id="sliderAmount" style="text-align: right;">456</div>
        </div>
    </div>
Javascript:
    <script>
 
  var sAm
    function paramS() {
        var sliderList = document.getElementsByTagName('input');
var sliderArray = [].map.call(sliderList, function(el) {
  return el.id;
});
call_me(sliderArray);

        function call_me(params) {
            for (i = 0; i < params.length; i++) {
                var slider = document.getElementById(params[i]);
                slider.addEventListener('input', sliderChange);
            }
        }
    }
    function isitTime(utton, sliderAmount) { //oninput of slider calls this function to prevent refereshing the page while sliding
        window.isittime = 0;
        sAm = sliderAmount;
      
    }
    function sliderChange() {
        var sliderDiv = document.getElementById(sAm);
        sliderDiv.innerHTML = this.value;
        console.log(sliderAmount);
    }  
function updateSlider(sliderAmount, utton) {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
            }
        }
        xhr.open('get', 'control?cmd=event,' + utton + 'event=' + sliderAmount, true); //generating the event+values vor all the slider
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
        xhr.send();
        window.isittime = 1;
    }
    </script>

Die Funktion paramS() wird am nach dem Erstellen aller Elemente ausgeführt. Es funktioniert alles wie es soll. Aber ich schau mir auf jeden Fall deinen Vorschlag nochmal genauer an. Der sieht wesentlich eleganter aus!!!
 

chromo23

Neues Mitglied
Also auf jeden Fall super! Sieht besser aus und funktioniert. Danke vielmals!!!
Eine letzte Frage diesbezüglich.
Warum funktioniert folgendes nicht? Ich wollte den Inhalt von "slider" gerne weitergeben. Klappt aber nicht.
Javascript:
function sliderChange(event) {
        // Den Slider, der das Event ausgelöst hat,
        // finden wir unter event.target:
        slider = event.target;
        sliderAmount = event.target.value;
        .
        .
        .
        xhr.open('get', 'control?cmd=event,' + slider + 'event=' + sliderAmount, true); //generating the event+values vor all the slider
.
.
.

Output:
Code:
 HTTP: event,[object HTMLInputElement]event=711
sliderAmount funktioniert
slider nicht

Edit: slider.id :smile:
Edit2: Also nochmal... Danke, danke, danke!!!
 
Zuletzt bearbeitet:

Sempervivum

Senior HTML'ler
slider ist ein HTML-Element und kein String, slider ist dagegen ein String. In einer URL kannst Du nur Strings einsetzen. Setzt Du ein HTML-Element ein, macht Javascript eine automatische Umwandlung in eine Stringdarstellung wobei dann "[object HTMLInputElement]" heraus kommt.

Was meinst Du mit 'Inhalt von "slider"'?
 

chromo23

Neues Mitglied
slider ist ein HTML-Element und kein String, slider ist dagegen ein String. In einer URL kannst Du nur Strings einsetzen. Setzt Du ein HTML-Element ein, macht Javascript eine automatische Umwandlung in eine Stringdarstellung wobei dann "[object HTMLInputElement]" heraus kommt.
(Sorry, wenn das ne doofe Frage ist aber ich steh bei Javascript echt aufm Schlauch)
Ich hoffe du hast die Edits im Letzen Post gelesen..
 

Sempervivum

Senior HTML'ler
Ja, die Edits habe ich gelesen, anscheinend funktioniert jetzt alles?
Besser keine Edits sondern ein neuer Post als PS. Denn für die Edits bekommt man keine Benachrichtigung und sie werden leicht übersehen.
 
Werbung:

Neueste Beiträge

Oben