1

I have a simple slider divided into 24 steps (0-23), each representing an hour of the day. My objective is to animate the slider once so that every second, the value of the input and the slider increases by one - starting from 0 to 23 and then stopping (a total of 24 seconds). And then stop (loop ends).

.map-overlay input {
    background-color: transparent;
    display: inline-block;
    width: 100%;
    position: relative;
    margin: 0;
    cursor: ew-resize;
}

<div class='map-overlay-inner'>
    <h2>Passengers by hour</h2>
    <label id='variable'></label>
    <input id='slider' type='range' min='0' max='23' step='1' value='0' />
</div>

var variables = [ '0', '1', '2', '3', '4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23',
];

function filterBy(variable) {

    var filters = ['==', 'variable', variable];
    map.setFilter('circles', filters);
    map.setFilter('labels', filters);

    // Set the label to the hour
    document.getElementById('variable').textContent = variables[variable];
}
document.getElementById('slider').addEventListener('input', function(e) {
    var variable = e.target.value
    filterBy(variable);
});

At this point, the value changes on manual input with e.target.value

When I implement this solution to move the slider by one, however, the textContent does not change and for some reason the slider jumps from 1 to 11. Why does this happen and can anyone recommend a solution?

var myVar = setInterval(myTimer, 1000);
function myTimer() {
    document.getElementById("slider").value += 1;
}
iskandarblue
  • 7,208
  • 15
  • 60
  • 130

2 Answers2

2

This is because the value of document.getElementById("slider").value is a string. On the console, if you run "1" + 1 you would get the result "11" with a type of string. It's odd that it does not automatically return a number despite being a slider.

The fix would be to try and convert the value to a number. For the label, since you're only expecting text in it, you can just set the innerHTML of it with the value of the slider (assuming that's what you wanted to do):

var input = document.getElementById('slider');
var label = document.getElementById('variable');

//initialize label
label.innerHTML = input.value;

function myTimer() {
  var newValue = parseInt(input.value) + 1;
  input.value = newValue;
  label.innerHTML = newValue;
}

setInterval(myTimer, 1000);
<label id='variable'></label>
<input id='slider' type='range' min='0' max='23' step='1' value='0' />

As for the progression of the value, try the following:

var input = document.getElementById('slider');

// returns 0
input.value = 0;
console.log(input.value); 

// returns 1, because you give it a value of "01"
input.value += 1;
console.log(input.value); 


// returns 11, because you give it a value of "011"
input.value += 1;
console.log(input.value); 

// returns 23 because you give it a value of "111" but the max is 23
input.value += 1;
console.log(input.value); 
Brian
  • 1,873
  • 16
  • 25
  • This fixes the slider problem, but the `filterBy()` function does not work, nor does the `textContent` change. How should I change the `.addEventListener('input', function(e)` in this case? – iskandarblue Mar 08 '17 at 21:57
  • what exactly is the filterBy supposed to do? – Brian Mar 08 '17 at 22:02
  • it filters two layers on the map by the input variable – iskandarblue Mar 08 '17 at 22:18
  • programatically changing the values of the input won't fire an event. what you can do is manually call `filterBy(newValue)` inside the interval, but only if the value changed. if you do so, you won't need to modify the function you have for filterBy. You will still need the event handler in case the slider is dragged. – Brian Mar 08 '17 at 22:35
1

You have two flaws in your code:

  • To increment the slider's value, use slider.stepUp(). Your line document.getElementById("slider").value += 1 does not work as intended since the value is a string which is initially '0'. In Javascript, '0' + 1 evaluates to '01' and subsequently '01' + 1 evaluates to '011' which, when converted to a number, is interpreted as 11.

  • Also, the input event is only fired for user input, not when programmatically changing the slider's value. In this case, you could e.g. manually dispatch an input event which would then be handled by your event listener as intended. See also: Trigger change Event when the Input value changed Programatically?

Also, map in filterBy() is undefined for me.

Example:

var slider = document.getElementById("slider");
var variable = document.getElementById('variable');

slider.addEventListener('input', function(e) {
    variable.textContent = slider.value;
});

var interval = setInterval(function() {
  slider.stepUp();
  slider.dispatchEvent(new Event('input'));
  if (slider.value == 23) clearInterval(interval);
}, 1000);
<label id='variable'></label>
<input id='slider' type='range' min='0' max='23' step='1' value='0' />
Community
  • 1
  • 1
le_m
  • 19,302
  • 9
  • 64
  • 74