forked from fixin.me/fixin.me
Check for out of range float values
Remove unsupported attribute `[maxlength]` from `input[number]`.
This commit is contained in:
@@ -101,22 +101,14 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def number_field(method, options = {})
|
||||
attr_type = object.type_for_attribute(method)
|
||||
case attr_type.type
|
||||
case object.type_for_attribute(method).type
|
||||
when :float, :double
|
||||
options[:value] = object.public_send(method)&.to_scientific
|
||||
options[:step] ||= :any
|
||||
options[:min] ||= Float::MIN_15
|
||||
options[:max] ||= Float::MAX_15
|
||||
# Longest possible number (written not using exponent):
|
||||
# sign (1), leading 0 (1), dot (1), exponent 0s (307), digits (15).
|
||||
# This is only upper bound, which cannot guarantee the number won't fall
|
||||
# out of range.
|
||||
# TODO: add `[pattern]` to limit precision and (possibly) replace `[maxlength]`?
|
||||
# NOTE: `[pattern]` is unavailable on `input[type=number]` and `[min]/[max]` is
|
||||
# unavailable on `input[type=text]`.
|
||||
options[:maxlength] ||= 3 + Float::MIN_10_EXP + Float::DIG
|
||||
options[:min] ||= Float::MIN_15.to_scientific
|
||||
options[:max] ||= Float::MAX_15.to_scientific
|
||||
options[:oninput] = 'numberValidate(event)'
|
||||
options[:size] ||= 6
|
||||
options[:step] ||= :any
|
||||
options[:value] = object.public_send("#{method}_before_type_cast")
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
@@ -53,6 +53,27 @@ function formValidate(event) {
|
||||
}
|
||||
window.formValidate = formValidate
|
||||
|
||||
// Pattern for number precision verification. Should accept all number formats
|
||||
// accepted by Kernel#Float. Lookahead checks the number of significant digits
|
||||
// in mantissa, following expression makes sure there is only one dot.
|
||||
const numberRegExp = /^\-?(?=(?:\.?0)*(?:\.?\d){1,15}?(?:\.?0)*\.?(?:[eE]|$))(?<mantissa>\d*\.?\d+|\d+\.)(?:[eE]\-?\d{1,3})?$/
|
||||
|
||||
// Validation of input[type=number] value precision.
|
||||
function numberValidate(event) {
|
||||
var input = event.target
|
||||
|
||||
input.setCustomValidity("")
|
||||
if (!input.validity.valid) return
|
||||
|
||||
var match = numberRegExp.exec(input.value)
|
||||
if (!match ||
|
||||
(parseFloat(input.value) == 0.0 && match.groups['mantissa'].match(/[1-9]/))) {
|
||||
// TODO: move message to locales
|
||||
input.setCustomValidity("Please select a value within range of double precision floating-point format.")
|
||||
}
|
||||
}
|
||||
window.numberValidate = numberValidate
|
||||
|
||||
|
||||
// Turbo stream actions.
|
||||
const FORM_CONTROLS = ["BUTTON", "FIELDSET", "INPUT", "OPTGROUP", "OPTION", "SELECT",
|
||||
|
||||
Reference in New Issue
Block a user