When the number is empty, its value isNaN. So one needs to test for that, like in \`isNaN(gain) ? 0 : gain\`. Wish: option to set a default for when isNaN.
When typed number falls outside of range (e.g. when using Range to select item from array), result of array reference is \`undefined\`. Wish: option to ‘squeeze’ value to always be in range.
To always have correct values—automatically when ‘ranging’ an array—I now have:
squeeze = (x, r) => {
const range = Array.isArray(r) ? [0, r.length - 1] : r
return isNaN(x) ? range[0] : x < range[0] ? range[0] : x > range[1] ? range[1] : x
}
What about Range of dates (with custom steps, i.e. 6h or 2days or ...)?
I guess with current construct there would be quite a lot of transformation and formatting if at any possible.
Or does it "deserve" its own input?
Any suggestions / pointers?
I think that’s outside the scope of the input, because you’re intended to be able to type into the number input to set the value. Though perhaps a date range could let you type a date in… Feel free to upvote this issue: https://github.com/observablehq/inputs/issues/38
Weirdly enough, this fails:
viewof x = Range([-0.5857864376269049, 2])
Symptom: variable x never reaches -0.586, although the value displayed in the number input element does
This also fails:
viewof x = Range([-0.5857864376269049, 2], {step:0.0001})
Symptom: variable x is never updated, although the number input element does.
This appears to be a precision problem with the behavior of native inputs. I would suggest not relying on such high precision for user input. For example, an extent of [-0.586, 2] will be fine. You can verify this, given an input:
<input type="range" min="-0.5857864376269049" max="2" value="-0.5857864376269049">
The input.valueAsNumber is -0.585786437626905 (note the rounding), and after calling input.checkValidity(), input.validity.rangeUnderflow is true. Changing the minimum to -0.585786437626905 fixes this problem.
The other problem here is that the default number format (number.toLocaleString) will only give you three decimal places, so to be compatible with Observable’s Range input, you need the number input to be valid, too. So I recommend using -0.586 as the minimum, or if you really want a high precision input, pass {format: x => x} to force the number to display all the digits.
Thanks, Mike. I had already figured out how to avoid the problem. It's just that that weird number came out as a calculation -- 2 * (Math.cos(Math.PI / 4) - 1) and I thought it was worth mentioning. From here on, limits are best written as literals!
You can style it with external CSS, but this is not recommended. Observable Inputs are intended to provide a well-designed, consistent appearance by default. For more customization, see https://observablehq.com/@bartok32/diy-inputs
Set the attribute directly on the two input elements of the form that is returned. For example with D3:
> d3.select(viewof d).selectAll("input").attr("disabled", "disabled") // disable
> d3.select(viewof d).selectAll("input").attr("disabled", null) // enable