onChange-Ereignis für den HTML5-Bereich

70

Derzeit wird bei jedem Schritt das Ereignis onChange an meinen Bereichseingängen ausgelöst.

Gibt es eine Möglichkeit, das Auslösen dieses Ereignisses zu verhindern, bis der Benutzer den Schieberegler losgelassen hat?

Ich verwende den Bereich, um eine Suchabfrage zu erstellen. Ich möchte in der Lage sein, die Suche jedes Mal auszuführen, wenn das Formular geändert wird, aber es ist zu viel, bei jedem Schritt der Bewegung des Schiebereglers eine Suchanforderung auszugeben.


Hier ist der Code wie er ist:

HTML:

<div id="page">
    <p>Currently viewing page <span>1</span>.</p>
    <input class="slider" type="range" min="1" max="100" step="1" value="1" name="page" />
</div>

JavaScript:

$(".slider").change(function() {
    $("#query").text($("form").serialize());
});

Hilft das?

WilliamMayor
quelle
7
Dies ist ein Fehler in der Implementierung von WebKit und IE aufgrund einer Mehrdeutigkeit in der HTML-Spezifikation. Die Spezifikation wurde inzwischen klargestellt, dass das Änderungsereignis erst ausgelöst werden sollte, wenn der Knopf losgelassen wird. Um Werte zu erhalten, während der Benutzer den Knopf bewegt, sollte das Ereignis 'input' verwendet werden. WebKit und IE haben diesen Implementierungsfehler jedoch noch nicht behoben. Überarbeitung der HTML-Spezifikation: html5.org/tools/web-apps-tracker?from=7786&to=7787
JeremiahLee

Antworten:

66

Verwenden Sie für den endgültig ausgewählten Wert:

 $(".slider").on("change", function(){console.log(this.value)});

Verwenden Sie diese Option, um den inkrementellen Wert als gleitend abzurufen:

$(".slider").on("input", function(){console.log(this.value)});
kravits88
quelle
2
Dies funktioniert gut in Firefox und Chrome, aber nicht in Safari. Safari löst das Änderungsereignis aus, während Sie gleiten. Zumindest bis sie mit der Implementierung des Fixes auf der Grundlage des geänderten Standards fertig sind.
Baohouse
Cool, danke - wusste nichts von dem "Input" -Event. Aber das habe ich gesucht! (y)
KS
14

Etwas spät, aber ich hatte neulich das gleiche Problem. Hier ist meine Lösung mit jQuery bind / trigger:

(function(el, timeout) {
    var timer, trig=function() { el.trigger("changed"); };
    el.bind("change", function() {
        if(timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(trig, timeout);
    });
})($(".slider"), 500);

Binden Sie jetzt einfach Ihre Funktion an das 'geänderte' Ereignis.

Arwyn
quelle
2
Dies ist eine gute Problemumgehung, hat jedoch den Nachteil, dass der Trigger bei allen Elementen, die auf den Selektor ".slider" reagieren, jedes Mal geändert wird, wenn sich nur eines tatsächlich ändert. Ich (function($el, timeout) { var timer; $el.bind("change", function() { var $me = $(this); if (timer) { clearTimeout(timer); } timer = setTimeout(function() { $me.trigger("changed"); }, timeout); }); })($(.slider), 500);
ändere
9

Bah!

Verwenden Sie stattdessen das onmouseupEreignisonChange

Toastar
quelle
4
Ich hatte darüber nachgedacht, mich aber aus zwei Gründen dagegen entschieden: Es ist umständlich, mit nicht geänderten Slider-Werten umzugehen (Moll), und ich kann nicht davon ausgehen, dass Benutzer das Formular mit einer Maus bearbeiten (Major). Ich habe immer noch keine richtige Antwort auf die Frage, aber ich fühle mich schlecht, wenn ich keine Antwort als richtig markiere. Sie sind korrekt (wie in, sie funktionieren), aber sie beantworten die Frage nicht wirklich.
WilliamMayor
2
Sie müssen auch die Ereignisse hinzufügen: onkeyup(falls die Tastatur verwendet wird) und ontouchend(falls ein Touchscreen verwendet wird).
iRon
6

Ein Problem ist, dass AFAIK HTML5 nicht definiert, wann das onchangeEreignis ausgelöst werden soll, sodass es höchstwahrscheinlich von Browser zu Browser unterschiedlich ist. Und Sie müssen auch berücksichtigen, dass ein Browser einen nicht input type=rangeals Schieberegler rendern muss .

Sie können nur einen Mechanismus einbauen, um sicherzustellen, dass Ihre Suche nicht zu oft ausgelöst wird. Überprüfen Sie beispielsweise, ob eine Suche gerade ausgeführt wird, und brechen Sie sie ab, wenn dies der Fall ist, oder stellen Sie sicher, dass die Suche bei a ausgelöst wird maximal alle x Sekunden.

Schnelles Beispiel für Letzteres (nur ein kurzer Hack, ungetestet).

var doSearch = false;

function runSearch() {
   // execute your search here 
}

setInterval(function() {
  if (doSearch) {
     doSearch = false;
     runSearch();
  }
}, 2000); // 2000ms between each search.

yourRangeInputElement.onchange = function() { doSearch = true; }
RoToRa
quelle
5

Pure JS hier:

myInput.oninput = function(){
    console.log(this.value);
}

oder

myInput.onchange = function(){
    console.log(this.value);
}

quelle
2

gravediggin aber wenn Sie es brauchen überprüfen js drosseln oder debounce Funktionen

Verwendung:

//resize events gets processed 500ms after the last Event
addEventListener("resize", _debounce(function(){ foo;}, 500));

//resize events get processed every 500ms
addEventListener("resize", _throttle(function(){ foo;}, 500));

Code:

/*waits 'delay' time after the last event to fire */
_debounce = function(fn, delay) {
    var timer = null;
    return function() {
        var context = this,
            args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function() {
            fn.apply(context, args);
        }, delay);
    };
};


/* triggers every 'treshhold' ms, */
_throttle = function(fn, threshhold, scope) {
    threshhold = threshhold || 250;
    var last,
        deferTimer;
    return function() {
        var context = scope || this;

        var now = +new Date(),
            args = arguments;
        if (last && now < last + threshhold) {
            // hold on to it
            clearTimeout(deferTimer);
            deferTimer = setTimeout(function() {
                last = now;
                fn.apply(context, args);
            }, threshhold);
        } else {
            last = now;
            fn.apply(context, args);
        }
    };
};
Mons Droide
quelle
1

Folgendes verwende ich zum Erfassen des 'Änderungsereignisses' für den Schieberegler für den HTML5-Bereich:

HTML:

<form oninput="output1.value=slider1.value">
    <input type="range" name="slider1" value="50"/>
    <output name="output1" for="slider1">50</output>
</form>

JavaScript:

var $slider = $('input[name="slider1"]');

$slider.bind('change', function(e) {
    e.preventDefault();
    console.log($(this).val());
});

Sie können das 'Klick'-Ereignis auch an den Bereichsregler binden, wenn Sie seinen Wert zurückgeben möchten, wenn darauf geklickt (oder sogar gezogen) wurde. Stellen Sie sich das wie ein Mouseup-Ereignis vor. (Ich habe das versucht, aber der Schieberegler hörte nicht auf, nachdem ich auf den Schieberegler geklickt hatte.)

JavaScript:

$slider.bind('click', function(e) {
    e.preventDefault();
    console.log($this).val());
}

Nebenbei bemerkt, dies gibt eine Zeichenfolge zurück. Stellen Sie daher sicher, dass Sie gegebenenfalls 'parseInt ($ (this) .value ())' verwenden.

Hoffe das hilft.

Scott
quelle
1

Ich verwende mehrere HTML5-Standardschieberegler auf derselben Seite mit dem folgenden Setup:

  • Das Ausgabe-Tag auf der Seite ändert den Wert, wenn der Schieberegler mithilfe des oninputEreignisses verschoben wird
  • Ein changeEreignis wird bei der Freigabe einmal ausgelöst

Getestet mit dem neuesten Chrome und gut kompilierbar auf einer Himbeere mit Node und Socket.io.

<output id="APIDConKpVal"></output>&nbsp; <input type="range"
             class="PIDControlSlider"
             min="0"
             max="1500"
             step="1"
             id="APIDConKp"
             oninput="APIDConKpVal.value=value"/>

<output id="APIDConKiVal"></output>&nbsp; <input type="range"
             class="PIDControlSlider"
             min="0"
             max="2000"
             step="1"
             id="APIDConKi"
             oninput="APIDConKiVal.value=value"/>

Ein einfacher Javascript-Code erstellt die Listener. Möglicherweise müssen Sie verschiedene Ereignisse ausprobieren, anstatt sie in der letzten Zeile zu ändern, um zu sehen, was zu Ihnen passt.

window.onload=function()
{
 var classname = document.getElementsByClassName("PIDControlSlider");

    var myFunction = function() {
        var attribute = this.getAttribute("id");
//Your code goes here
        socket.emit('SCMD', this.getAttribute("id")+' '+ this.value);
    };

    for(var i=0;i<classname.length;i++){
        classname[i].addEventListener('change', myFunction, false);
    }
}
Paolo
quelle
0

ein anderer Vorschlag:

$(".slider").change(function(){    
  if (this.sliderTimeour) clearTimeout(this.sliderTimeour);
  this.sliderTimeour = setTimeout(function(){
    //your code here
  },delayTimeHere);
});
Sagiv Ofek
quelle
Dieser Code scheint mit jQuery 1.9.1 in Konflikt zu stehen, da er immer wieder einen Fehler auslöst. Ich fand jedoch, dass Arwyns Antwort unten funktioniert.
Julian Dormon
0

Sie können versuchen, blurevent zu verwenden . Natürlich hat es auch seine Grenzen, aber es ist nur ein weiterer Vorschlag :)

Sie können auch versuchen, die und Ereignisse zu kombinieren blur, um verschiedene Situationen zu erfassen : Wenn der Benutzer die Auswahl mit Tastaturpfeilen und Treffern trifft , wenn der Benutzer die Auswahl mit der Tastatur trifft und sich auf den Schieberegler konzentriert und wenn er die Maus verwendet . Es könnte sogar möglich sein, nur das und zu kombinieren .onkeyuponmouseupblur<Tab>onkeyuponmouseuponkeyuponmouseup

Trotzdem müssen Sie einfach überprüfen, ob sich der Wert geändert hat oder nicht, und den erforderlichen Code erst ausführen, nachdem eine Änderung vorgenommen wurde.

Michal Trojanowski
quelle
0

onchange funktioniert einwandfrei, aber ich musste den Wert aktualisieren, während ich ihn verschob.

var interval;
$("#rangeinput").mousedown(function(event){
    interval = setInterval(function(){
        $("#output").html($("#rangeinput").val());
        console.log("running");
    },150);
});

$("#rangeinput").mouseup(function(event){
    clearInterval(interval);
});

http://jsbin.com/vibuc/1/

Alejandro
quelle
0

Fügen wir der Sammlung eine einfache ES6-Alternative hinzu:

let timer;

const debounceChange = (value, callback) => {
    clearTimeout(timer);
    timer = setTimeout(() => callback(value), 500);
};

In JSX würde es so aussehen:

<input type="range" onChange={e => debounceChange(e.target.value, props.onChange)}/>
Marco Kerwitz
quelle