Reputation: 91
I have three input type='range' fields that have different max values but share the same capacity. This capacity is decreased with every change on either of the three inputs. When the capacity reaches 0 I am supposed to prevent the input fields from moving right ( from increasing their value ) and only move left, but I dont know how to do it using JS and jQuery
here is the html for the inputs
<input type="range" class="slider" id="woodSlider" min="0" value="0" max="1558">
<input type="range" class="slider" id="ironSlider" min="0" value="0" max="2555">
<input type="range" class="slider" id="stoneSlider" min="0" value="0" max="2451">
and here is the code that decreases the capacity:
$("input").change(function() {
$("#capacityLeft").html(parseInt(holding.capacity) -
$("#woodSlider").val() -
$("#ironSlider").val() -
$("#stoneSlider").val());
if(parseInt($("#capacityLeft").html()) <= 0) {
// TODO: FIND OUT HOW TO STOP THE SLIDERS FROM MOVING
}
});
Upvotes: 6
Views: 9296
Reputation: 2386
Just to expand on both answers, in regard to the OP's question // TODO: FIND OUT HOW TO STOP THE SLIDERS FROM MOVING
, it must be said that the change event for input type range is not cancelable. Thus, preventDefault
etc. won't work on it and you might very quickly see the slide moving first (because it can't be canceled) and then see it moving to the new position JavaScript changed it to.
TL;DR you can't stop the slider from moving, but you can update the value.
Here's an example of what I mean, note that if you click on the slider itself you'll see it quickly moving and then falling back to the JS assigned position:
const example = document.getElementById('example');
example.addEventListener('click', (ev) => {
// needs this because input change event isn't cancellable, clicking on input will first change input regardless (e.g., it will go from 0 to 1, but then the script will return it to 0)
const input = example.querySelector('input');
input.value = input.value === "1" ? "0" : "1";
ev.preventDefault();
ev.stopImmediatePropagation();
}, {capture: true});
<div id="example">
OFF<input type="range" min="0" max="1">ON
</div>
<div>now click twice directly on one of the range input extremities</div>
That's also why @Andrew's answer above requires a variable to be stored somewhere else recording the state of the input.
Upvotes: 1
Reputation: 1
I fiddled around for a while, and this is what I was able to custom set the input range's value with (this code basically implements a "toggle" button):
let input = document.getElementById('myInput');
let currentValue = 0;
input.onclick = function(e) {
currentValue = 1 - currentValue;
e.target.value = currentValue;
return false;
}
<input id="myInput" type="range" min="0" max="1" value="0" style="width: 600px;" />
I used onclick
because I wanted it to respond every time the user clicks anywhere on the input range, not just when the user "changes the value" according to the browser. Obviously, use oninput
or onchange
if you only want to fire an event when the user changes the slider position.
It does appear to be the case that you need to manually set/override the e.target.value
as the return false;
is not really doing anything. In fact, the above code works just the same without returning false.
For mobile, however, you need to use ontouchstart
instead of onclick
. You also need to return false;
for it to work.
Upvotes: 0
Reputation: 36965
Okay, so you can use event.preventDefault()
to stop an event. You should bind a function to onchange
or oninput
events on these range sliders and calculate the sum, check if it exceed the max, then stop the event if it does.
Here's a pure JS solution (fiddle link), could be easily rewritten with jQuery.
var maxTotal = 150, // define the max sum of values
inputs = [].slice.call(document.getElementsByTagName('input')), // refrence to the elements
getTotal = function(){ // helper function to calculate the sum
var sum = 0;
inputs.forEach( function(input){
sum += parseInt(input.value, 10);
});
return sum;
},
maxReached = function(e){ // check if the max is reached
var sum = getTotal(), target;
if(sum > maxTotal){
target = e.target;
// set the max possible value if the user, for example, clicks too far to the right
target.value = target.value - (sum - maxTotal);
// next line is just for demonstrational purposes
document.getElementById('total').innerHTML = getTotal();
// prevent increasing the value
e.preventDefault();
return false;
}
// next line is just for demonstrational purposes
document.getElementById('total').innerHTML = getTotal();
// everything's fine, nothing to do.
return true;
};
// attach the maxReached function to your inputs
inputs.forEach( function(input){
input.addEventListener('input', maxReached );
});
Upvotes: 11