onChange event for HTML5 range
HtmlFormsRangeOnchangeHtml Problem Overview
Currently the onChange event on my range inputs is firing at each step.
Is there a way to stop this event from firing until the user has let go of the slider?
I'm using the range to create a search query. I want to be able to run the search every time the form is changed but issuing a search request at each step of the slider's movement is too much.
Here's the code as it stands:
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());
});
Does that help?
Html Solutions
Solution 1 - Html
Use for final selected value:
$(".slider").on("change", function(){console.log(this.value)});
Use to get incremental value as sliding:
$(".slider").on("input", function(){console.log(this.value)});
Solution 2 - Html
Bit late, but I had the same problem the other day. Here is my solution using 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);
Now just bind your function to the 'changed' event instead.
Solution 3 - Html
Bah!
Use onmouseup
event Rather then onChange
Solution 4 - Html
One problem is that AFAIK the HTML5 doesn't define when the onchange
event is supposed to fire, so it is most likely different from browser to browser. And you also have to consider, that a browser doesn't actually have to render an input type=range
as a slider.
Your only choice is that you have to build in a mechanism to make sure that your search isn't triggered too often, for example, check if a search is currently running and abort if it is, or make sure that searches are triggered at a maximum of every x seconds.
Quick example for the latter (just a quick hack, untested).
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; }
Solution 5 - Html
Pure JS here:
myInput.oninput = function(){
console.log(this.value);
}
or
myInput.onchange = function(){
console.log(this.value);
}
Solution 6 - Html
gravediggin but if you need it check js throttle or debounce functions
Usage:
//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);
}
};
};
Solution 7 - Html
Here's what I use for capturing the 'change event' for the html5 range slider:
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());
});
You can also bind the 'click' event to the range slider if you want to return its value when it has been clicked (or even dragged). Think of it like a 'mouseup' event. (I did try that but the slider didn't stop after I had clicked on the slider.)
JavaScript:
$slider.bind('click', function(e) {
e.preventDefault();
console.log($this).val());
}
On a side note, this returns a string so make sure you use 'parseInt($(this).value())' when appropriate.
Hope this helps.
Solution 8 - Html
I use several HTML5 default sliders in the same page with the following setup:
- Output tag in the page changes value when the slider is moved using the
oninput
event - A
change
event is triggered once on release
Tested with the latest Chrome and compiles well on a Raspberry with Node and Socket.io.
<output id="APIDConKpVal"></output> <input type="range"
class="PIDControlSlider"
min="0"
max="1500"
step="1"
id="APIDConKp"
oninput="APIDConKpVal.value=value"/>
<output id="APIDConKiVal"></output> <input type="range"
class="PIDControlSlider"
min="0"
max="2000"
step="1"
id="APIDConKi"
oninput="APIDConKiVal.value=value"/>
A simple Javascript code creates the listeners. You might need to try different events instead of 'change' in the last line to see what fits you.
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);
}
}
Solution 9 - Html
another suggest:
$(".slider").change(function(){
if (this.sliderTimeour) clearTimeout(this.sliderTimeour);
this.sliderTimeour = setTimeout(function(){
//your code here
},delayTimeHere);
});
Solution 10 - Html
You can try to use blur
event. Of course it also has it's limitations but it's just another suggestion :)
You can also try to combine the blur
, onkeyup
and onmouseup
events to try to catch different situations: blur
when the user makes the selection with keybord arrows and hits <Tab>
, onkeyup
when the user makes the selections with keyboard and stays focused on the slider, and onmouseup
when he uses the mouse. It might be even possible to only combine the onkeyup
and onmouseup
.
Still you will have to make a simple check if the value has changed or not and run neccessary code only after a change occured.
Solution 11 - Html
onchange works just fine , but I needed to update the value while sliding it.
var interval;
$("#rangeinput").mousedown(function(event){
interval = setInterval(function(){
$("#output").html($("#rangeinput").val());
console.log("running");
},150);
});
$("#rangeinput").mouseup(function(event){
clearInterval(interval);
});
Solution 12 - Html
Let's add a simple ES6 alternative to the collection:
let timer;
const debounceChange = (value, callback) => {
clearTimeout(timer);
timer = setTimeout(() => callback(value), 500);
};
When used in JSX it would look like this:
<input type="range" onChange={e => debounceChange(e.target.value, props.onChange)}/>