0

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?

6
  • Here is an example of a pattern input field. Have you tried anything to achieve your goal? Commented Jul 9, 2019 at 17:27
  • Can you post your complete code here ? Commented Jul 9, 2019 at 19:11
  • @Kryptur I'm not sure if you've read the question, but I have the pattern working. That's not at all what the question was about. The code you posted is completely irrelevant to the question. I want to enforce values between "min" and "max" for a input type="text" the same way the browser does it for type="number". Commented Jul 10, 2019 at 10:01
  • @Ouroborus yes they are for input type="number". The question is how to get them working for input of type text, due to the terrible localization support for type="number". Commented Jul 10, 2019 at 10:02
  • So stick to the question I gave you. What have you tried? Commented Jul 10, 2019 at 10:31

1 Answer 1

1

$("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

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for the suggestion, but what I'm looking for is the same behaviour that an input type="number" field has. I don't want the input to be overriden to min/max value after typing, but upon the submit - and display a message accordingly. See: i.imgur.com/MLRdbFy.gifv
sure @mhpcc, but the problem with number input is, they don't accept characters like $ or ,. The only way around for you to get, all min,max,$ and , is using text input and override with JS
"I don't want the input to be overriden to min/max value after typing, but upon the submit - and display a message accordingly. See: i.imgur.com/MLRdbFy.gifv"
Yes, but how to achieve that in a good way has nowhere been mentioned. The only idea I've had is to globally check for forms and bind the validation of each field to the submit event - but even then I have no idea how to get the same dialog to display as the browser natively would for type="number" with min/max if the values are out of range. Checking on input or blur event of the fields themselves with a silent correction is not what I want, but the behaviour such as in the imgur gif.
I had a similar problem and couldn't find the answer anywhere. Finally I found out via the Firefox Developers Edition Inspector. My problem was the input would allow me to type in any value outside the min and max values. Here is what I found:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.