80

I am trying to format a number input by the user into currency using javascript. This works fine on <input type="text" />. However, on <input type="number" /> I cannot seem to be able to set the value to anything that contains non-numeric values. The following fiddle shows my problem

http://jsfiddle.net/2wEe6/72/

Is there anyway for me to set the value to something like $125.00?

I want to use <input type="number" /> so mobile devices know to bring up a keyboard for number input.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Danny
  • 7,368
  • 8
  • 46
  • 70
  • 7
    Can't you just display the $ in front of the control? Or do you want to give the users control over which currency they want to enter? In the latter case, I'm afraid only `type="text"` qualifies. – Mr Lister Feb 01 '13 at 16:41
  • @MrLister that is a really good point. That is probably what I'll end up doing. – Danny Feb 01 '13 at 16:49
  • If you want to allow the user to change the type of currency but still do `type="number"`, you can have a select box with the various currency symbols. Note that many countries put the currency symbol after the number instead of before. – RoboticRenaissance Nov 04 '16 at 19:58
  • Linked - [html5 input for money/currency](https://stackoverflow.com/q/24163889/104380) – vsync Apr 15 '20 at 08:57

6 Answers6

93

Add step="0.01" to the <input type="number" /> parameters:

<input type="number" min="0.01" step="0.01" max="2500" value="25.67" />

Demo: http://jsfiddle.net/uzbjve2u/

But the Dollar sign must stay outside the textbox... every non-numeric or separator charachter will be cropped automatically.

Otherwise you could use a classic textbox, like described here.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • 8
    Not what the OP asked for... if value="25.6" that's what will show... it should show "25.60" – patrick Jun 13 '17 at 00:46
  • 1
    [HTML5 specs/implementations of this are buggy](https://bugzilla.mozilla.org/show_bug.cgi?id=1003896) @patrick. What you want is not possible apart from [hackish, browsers-dependant solutions](https://stackoverflow.com/a/19205426/1654265), which will not work on Firefox, though. I've edited the fiddle BTW, since the `Globalize.format` function was now breaking it *at all* in FF, so I guess I should thank you for your feedback :) – Andrea Ligios Jun 13 '17 at 12:35
  • 1
    @AndreaLigios The link that you have described as classic textbox is exactly what I was looking for in formatting currency for the textbox. I had to make several changes, but it was a great start. – Jester Jan 23 '18 at 20:03
  • 1
    `min` has no sense here. I can easily set negative values – Green Feb 09 '18 at 12:21
  • 2
    @Green I'm on Firefox, and I cannot. That, however, is browser implementation specific, and in the end, I'm confident you understand [the difference between client-side and server-side validation](https://stackoverflow.com/a/28341208/1654265). I'm not sure what the downvote is really about, but thanks for the feedback. – Andrea Ligios Feb 09 '18 at 13:25
27

In the end I made a jQuery plugin that will format the <input type="number" /> appropriately for me. I also noticed on some mobile devices the min and max attributes don't actually prevent you from entering lower or higher numbers than specified, so the plugin will account for that too. Below is the code and an example:

(function($) {
  $.fn.currencyInput = function() {
    this.each(function() {
      var wrapper = $("<div class='currency-input' />");
      $(this).wrap(wrapper);
      $(this).before("<span class='currency-symbol'>$</span>");
      $(this).change(function() {
        var min = parseFloat($(this).attr("min"));
        var max = parseFloat($(this).attr("max"));
        var value = this.valueAsNumber;
        if(value < min)
          value = min;
        else if(value > max)
          value = max;
        $(this).val(value.toFixed(2)); 
      });
    });
  };
})(jQuery);

$(document).ready(function() {
  $('input.currency').currencyInput();
});
.currency {
  padding-left:12px;
}

.currency-symbol {
  position:absolute;
  padding: 2px 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="number" class="currency" min="0.01" max="2500.00" value="25.00" />
Danny
  • 7,368
  • 8
  • 46
  • 70
10

You guys are completely right numbers can only go in the numeric field. I use the exact same thing as already listed with a bit of css styling on a span tag:

<span>$</span><input type="number" min="0.01" step="0.01" max="2500" value="25.67">

Then add a bit of styling magic:

span{
  position:relative;
  margin-right:-20px
}
input[type='number']{
  padding-left:20px;
  text-align:left;
}
William Hagan
  • 305
  • 2
  • 9
  • This is nice and clean. the only problem is that clicking the currency symbol does not focus the input. – Mark W Jun 12 '15 at 16:56
  • That's a simple javascript problem. Click event on span to focus the input – frugalcoder Jun 14 '16 at 05:50
  • 11
    …or you could just use a ` – nils Jun 29 '16 at 16:58
4

It seems that you'll need two fields, a choice list for the currency and a number field for the value.

A common technique in such case is to use a div or span for the display (form fields offscreen), and on click switch to the form elements for editing.

Christophe
  • 27,383
  • 28
  • 97
  • 140
  • This is a _much_ better choice than letting the users type the currency. – Mr Lister Feb 01 '13 at 16:56
  • Sorry, but the jQuery example given here and CurrencyTextBox in Dojo give much more user-friendly methods of managing input and validation than two fields. Except on mobile, because you have to use a text keyboard. The ultimate irony is on my iPad, type="number" includes my locale's currency symbol, £. HTML really needs to catch up and provide something that switches to appropriate keyboard for currency. – Paul Stephen Withers Jun 25 '14 at 15:49
0

I did using this . This code snippet automatically format numbers into currency and prefix a dollar sign.

<div class="main">
  <h1>Auto Formatting Currency</h1>
  
  <form method="post" action="#">
  <label for="currency-field">Enter Amount</label>
  <input type="text" name="currency-field" id="currency-field" pattern="^\$\d{1,3}(,\d{3})*(\.\d+)?$" value="" data-type="currency" placeholder="$1,000,000.00">
  <button type="submit">Submit</button>
</form>

<p>Auto format currency input field with commas and decimals if needed. Text is automatically formated with commas and cursor is placed back where user left off after formatting vs cursor moving to the end of the input. Validation is on KeyUp and a final validation is done on blur.</p>

<p>To use just add the following to an input field:</p>
  
 <pre>data-type="currency"</pre>
  
</div><!-- /main -->

    html {
  box-sizing: border-box;
}

*, *:before, *:after {
  box-sizing: inherit;
}


body {
  background: #f5f5f5;
  color: #333;
  font-family: arial, helvetica, sans-serif;
  font-size: 32px;
}

h1 {
  font-size: 32px;
  text-align: center;
}

p {
  font-size: 20px;
  line-height: 1.5;
  margin: 40px auto 0;
  max-width: 640px;
}

pre {
  background: #eee;
  border: 1px solid #ccc;
  font-size: 16px;
  padding: 20px;
}

form {
  margin: 40px auto 0;
}

label {
  display: block;
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 10px;
}

input {
  border: 2px solid #333;
  border-radius: 5px;
  color: #333;
  font-size: 32px;
  margin: 0 0 20px;
  padding: .5rem 1rem;
  width: 100%;

}

button {
  background: #fff;
  border: 2px solid #333;
  border-radius: 5px;
  color: #333;
  font-size: 16px;
  font-weight: bold;
  padding: 1rem;
}

button:hover {
  background: #333;
  border: 2px solid #333;
  color: #fff;
}

.main {
  background: #fff;
  border: 5px solid #ccc;
  border-radius: 10px;
  margin: 40px auto;
  padding: 40px;
  width: 80%;
  max-width: 700px;
}

    // Jquery Dependency

$("input[data-type='currency']").on({
    keyup: function() {
      formatCurrency($(this));
    },
    blur: function() { 
      formatCurrency($(this), "blur");
    }
});


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);
}

https://codepen.io/akalkhair/pen/dyPaozZ

-1

The browser only allows numerical inputs when the type is set to "number". Details here.

You can use the type="text" and filter out any other than numerical input using JavaScript like descripted here

Community
  • 1
  • 1
mojoaxel
  • 1,440
  • 1
  • 14
  • 19