Reputation: 145
I'm trying to get the min="" and max="" attributes working on a number only input. Using <input type="number">
is out of the question due to terrible browser support for localization (dots should be thousand seperators, comma as decimal seperator, in input as well as in submit).
Optimally, upon form submit of every form, it would check for those certain fields if the number follows the pattern and is in the correct range, just like it would do natively for a type="number" input.
Alternatively, if it's possible or easier, I'm also open to using <input type="number" />
as long as pattern, currency signs and most importantly, commas are accepted in BOTH the value="123,12", the user input AND the value submitted to the server.
So far, I use pattern="-?(\d+|\d{1,3}(\.\d{3})*)(,\d+)?" which already validates the input except for min and max values.
Expected behaviour is that on a <input type="text" pattern"-?(\\d+|\\d{1,3}(\\.\\d{3})*)(,\\d+)?" min="0" max="1500" />
it would let me input any value I want, but when submitting the form, check if the numerically parsed value of the field (omitting currency signs or dots, understanding commas as decimal) is in the range between 0 and 1500. Optimally, but this doesn't matter as much, I'd also like the increment and decrement arrows with a step="0.01" such as for type="number" inputs.
Sadly, I'm completely out of ideas on how to implement this on a per-field basis and not run global javascript on each form submisssion button, preventing the default if not every input matches the criteria. But even if I did that, how would I go about displaying the correct (localized) warnings that type="number" would give me?
Upvotes: 0
Views: 6116
Reputation: 5712
$("input[data-type='currency']").on({
keyup: function() {
formatCurrency($(this));
},
blur: function() {
validateCurrency($(this));
formatCurrency($(this), "blur");
}
});
function validateCurrency(input){
var c = parseFloat(input.val().replace(/\,|$/g,'').replace('$',''));
if(c<input.attr('min')){
input.val(input.attr('min'));
}else if(c>input.attr('max')){
input.val(input.attr('max'));
}
}
function formatNumber(n) {
// format number 1000000 to 1,234,567
return n.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",")
}
function formatCurrency(input, blur) {
// appends $ to value, validates decimal side
// and puts cursor back in right position.
// get input value
var input_val = input.val();
// don't validate empty input
if (input_val === "") { return; }
// original length
var original_len = input_val.length;
// initial caret position
var caret_pos = input.prop("selectionStart");
// check for decimal
if (input_val.indexOf(".") >= 0) {
// get position of first decimal
// this prevents multiple decimals from
// being entered
var decimal_pos = input_val.indexOf(".");
// split number by decimal point
var left_side = input_val.substring(0, decimal_pos);
var right_side = input_val.substring(decimal_pos);
// add commas to left side of number
left_side = formatNumber(left_side);
// validate right side
right_side = formatNumber(right_side);
// On blur make sure 2 numbers after decimal
if (blur === "blur") {
right_side += "00";
}
// Limit decimal to only 2 digits
right_side = right_side.substring(0, 2);
// join number by .
input_val = "$" + left_side + "." + right_side;
} else {
// no decimal entered
// add commas to number
// remove all non-digits
input_val = formatNumber(input_val);
input_val = "$" + input_val;
// final formatting
if (blur === "blur") {
input_val += ".00";
}
}
// send updated string to input
input.val(input_val);
// put caret back in the right position
var updated_len = input_val.length;
caret_pos = updated_len - original_len + caret_pos;
input[0].setSelectionRange(caret_pos, caret_pos);
}
input {
border: 2px solid #333;
border-radius: 5px;
color: #333;
font-size: 32px;
margin: 0 0 20px;
padding: .5rem 1rem;
width: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" name="currency-field" id="currency-field" pattern="^\$\d{1,3}(,\d{3})*(\.\d+)?$" value="" data-type="currency" min="1000" max="1000000" placeholder="$200,000.00">
Minimum: 1000, Maximum: 1,000,000
Code by: Wade Williams @559wade
Tweaks: I just added validateCurrency()
function and executed it on blur
event to check for min
and max
Upvotes: 1