I have an <input type="number" step="1">
element for choosing font size. However, given the context of drawing on a large canvas, changing the number by 1 is barely noticeable. It would be more convenient for users if they could step up or down by 5 or 10 each time they click the arrow.
I still need to keep the step
attribute at 1 because the input should remain valid even with fine-grained values. Is there a way to achieve this behavior, like the below (pseudo) jump
attribute. I am open to Javascript solutions too but AFAIK there is no such event for when user clicks the arrows.
<input type="number" min="1" max="1000" step="1" jump="5" value="100" />
You could try this:
The input
event checks if the change in value matches the step value and adjusts it by the jump value accordingly.
Edit: In this case, to answer to your comment we will use a flag and add back the keydown
event.
Add a condition to the input event listener to prevent that unwanted behaviour in case you manually change the value
document.addEventListener('DOMContentLoaded', () => {
const input = document.querySelector('input[type="number"][min="1"][max="1000"][step="1"]');
const jump = parseInt(input.getAttribute('jump'), 10);
let previousValue = parseInt(input.value, 10);
let isManualChange = false;
input.addEventListener('keydown', (event) => {
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
event.preventDefault();
const currentValue = parseInt(input.value, 10);
if (event.key === 'ArrowUp') {
input.value = currentValue + jump;
} else if (event.key === 'ArrowDown') {
input.value = currentValue - jump;
}
previousValue = parseInt(input.value, 10);
isManualChange = false;
} else {
isManualChange = true;
}
});
input.addEventListener('input', (event) => {
const currentValue = parseInt(input.value, 10);
const step = parseInt(input.getAttribute('step'), 10);
if (!isManualChange && Math.abs(currentValue - previousValue) === step) {
if (currentValue > previousValue) {
input.value = previousValue + jump;
} else {
input.value = previousValue - jump;
}
}
previousValue = parseInt(input.value, 10);
});
});
<input type="number" min="1" max="1000" step="1" jump="5" value="100" />