Reputation: 165
I have code to create dynamic sliders for user to chose frequencies (from 118.000 Mhz to 136.975 Mhz). This list is dynamic so users have the capability to add or remove frequencies (and their sliders). But I have two problems:
Step is not working. It works perfectly for '15' or higher, but below this values, step doesn't work. If I use '10', steps become 20. Same if I choose 5 as step (which is the value that I need).
I can't make keyboard inputs work! I can make it work with static code (ex: static div, values, etc..), but not with this dynamic code. Also, there are two problems with keyboard inputs.
->
then slider moves to max value. If I type <-
then slider move to min value.Any tips?
var freqs = ["118000", "119550", "121725"];
for (var i = 0; i < freqs.length; i++) {
var $last = $('#freq_table').find('tbody').append("<tr><td class='col-md-2' id='value_freq_" + i + "'>oi</td><td class='col-md-8 center slider' id='td_slider_" + i + "'><div id='slider_" + i + "'></div></td></tr>");
var tmp = noUiSlider.create($('#slider_' + i).get(0), {
start: freqs[i],
step: 10,
range: {
'min': 118000,
'max': 136975
},
format: wNumb({
decimals: 3,
thousand: '.'
}),
}).on('update', function(values, handle) {
var id = this.target.id.slice(-1);
$('#value_freq_' + id).html(values[handle] + ' Mhz');
freqs[id] = values[handle];
});
var item = $('#slider_' + i).get(0);
var handle = item.querySelector('.noUi-handle');
handle.addEventListener('keydown', function(e) {
var value = Number(item.noUiSlider.get());
if (e.which === 37) {
item.noUiSlider.set(value - 10);
}
if (e.which === 39) {
item.noUiSlider.set(value + 10);
}
});
};
Upvotes: 4
Views: 2291
Reputation: 1074
The problems you're having are due to the wNumb
option decimals: 3
which affects the .get()
value in your keydown
handler. In effect it returns the value divided by 1000. To correct this, after calling .get()
, you then need to re-multiply the value by 1000 before adding/subtracting 5 (or whatever step value may be).
The other problem I noticed is the keydown
event was only bound to the last slider in your for
loop regardless of which slider you click/slide with the mouse. The reason for that is because the value of item
in the keydown
event was always #slider_2
(2 coming from the last loop iteration). To remedy that, assign a variable to the slider that was just clicked using the following statement var slider = $(this).closest('.noUi-target')[0];
.
A couple of UX enhancements
var freqs = ["118000", "119550", "121725"];
var stepSize = 5; // stepSize for the slider and arrow key increments
// Populate sliders by looping the freqs array
for (var i = 0; i < freqs.length; i++) {
// Append label and slider to table
var $last = $('#freq_table').find('tbody').append("<tr><td class='col-md-2' id='value_freq_" + i + "'>oi</td><td style='' class='col-md-8 center slider' id='td_slider_" + i + "'><div id='slider_" + i + "'></div></td></tr>");
// Create the noUiSlider
var tmp = noUiSlider.create($('#slider_' + i).get(0), {
start: freqs[i],
step: stepSize,
range: {
'min': 118000,
'max': 136975
},
format: wNumb({
decimals: 3,
thousand: '.'
}),
}).on('update', function(values, handle) {
var id = this.target.id.slice(-1);
$('#value_freq_' + id).html(values[handle] + ' Mhz');
freqs[id] = values[handle]; // Update the freqs array with new slider value
});
var item = $('#slider_' + i).get(0);
var handle = item.querySelector('.noUi-handle');
var keydownIteration = 1; // track iterations of keydown until keyup. To be used for slider acceleration.
// Add keyboard event to the slider handle
handle.addEventListener('keydown', function(e) {
var slider = $(this).closest('.noUi-target')[0];
var value = Number(slider.noUiSlider.get()) * 1000;
var multiplier = Math.floor(keydownIteration/10) + 1; // multiplier will be used to calculate slider acceleration
if (e.which === 37) {
slider.noUiSlider.set(Math.trunc(value - stepSize*multiplier));
}
if (e.which === 39) {
slider.noUiSlider.set(Math.trunc(value + stepSize*multiplier));
}
keydownIteration++; // increment counter
});
// Add keyboard event to the slider handle
handle.addEventListener('keyup', function(e) {
keydownIteration = 1; // resetting the iteration also resets accelaration
});
};
// When clicking on the label, focus and click the slider
$('#freq_table').on('click', 'td:first-child', function () {
$(this).closest('tr').find('.noUi-handle').focus().click();
});
#freq_table td:nth-child(2) {
width : 300px;
}
#freq_table td:first-child {
cursor : pointer;
}
#freq_table td {
padding : 10px;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/11.0.3/nouislider.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/wnumb/1.1.0/wNumb.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/11.0.3/nouislider.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="freq_table">
<thead>
</thead>
<tfoot>
</tfoot>
<tbody>
</tbody>
</table>
Upvotes: 2