31

This is strange behavior to me but on Webkit browsers (Chrome/Safari, not Firefox) if I include a space in a string of numbers in an <input type=number> then the value of that input is empty.

See this JSFiddle: http://jsfiddle.net/timrpeterson/CZZEX/5/

Here's the code:

<input id='withOutspace' type='number' value='123'>
<input id='with_space' type='number' value='123 123'>
<button>click</button>

$('button').click(function(){ 
    alert("withOut:"+$('#withOutspace').val()+" |||| with:"+$('#with_space').val());
});

If you go to this JSFiddle, you'll notice that the with_space input is empty. But if you put it in it a number that has a space or any non-numeric characters, the alert will say that input is empty.

Obviously, this is a disaster for form validation with credit card numbers, etc. so does anyone have a hack for this?

tim peterson
  • 23,653
  • 59
  • 177
  • 299

5 Answers5

43

The hack is to use type="tel" instead of type="number".

This solves the 2 main issues:

  1. It pulls up a number keypad on mobile devices
  2. It validates (and is not empty) with numbers or non-numbers as input.

Please see this JSFiddle: http://jsfiddle.net/timrpeterson/CZZEX/6/

tim peterson
  • 23,653
  • 59
  • 177
  • 299
  • 18
    The problem with using _tel_ is that it shows the phone number keyboard which does not have decimals or the negative sign which are often used in number fields (e.g. currency). (Tested on iPhone) – Jason Jan 24 '14 at 01:49
  • 2
    yes using `type="tel"` instead of `type="number"` depends on the use case. Credit cards (and phone numbers obviously) would be better with `type="tel"` because of the two reasons I mention above. – tim peterson Jan 24 '14 at 04:22
  • 5
    What about accessibility? Doesn't this prove to be troublesome for screenreaders? – scuds Oct 15 '15 at 01:17
5

I can suggest two ways. 1. Prevent chars in input

# updated to support more numerical characters related
$(window).keydown(function(e) {
  if($('input[type=number]').index($(e.target))!=-1) {
    if(
      ($.inArray(e.keyCode, [48,49,50,51,52,53,54,55,56,57,58,96,97,98,99,100,101,102,103,104,105,8,13,190,189]) == -1) // digits, digits in num pad, 'back', 'enter', '.', '-'
      || (e.keyCode == 190 && $(e.target).val().indexOf(".") != -1) // not allow double dot '.'
      || (e.keyCode == 190 && $(e.target).val().length == 0) // not allow dot '.' at the begining
    ) {
      e.preventDefault();
    }
  }
});

or 2. Change input's type on fly

$('input[type=number]').focus(function() {
    $(this).prop('type', 'text');
});

this allows to put whatever you want and change its type back onblur

$(this).blur(function() {
    $(this).prop('type', 'number');
});

But still you cannot store nonnumerical values in input with type=number, so val() will always return you empty string if it meets char or space.

So, at least you have to remove all garbage with .replace(/[^\d]/g, '') - that means "remove all except numbers" before you change type back

In my example I show both methods + clear input values.

alex
  • 479,566
  • 201
  • 878
  • 984
vladkras
  • 16,483
  • 4
  • 45
  • 55
  • 1
    I would add codes 97-106 (numpad numbers) to the allowed list too. – mcm69 Feb 24 '14 at 09:02
  • The _event wall_ described here is the best workaround I've found so far – fguillen Mar 02 '15 at 17:54
  • I'm including all this _keyCodes_ `48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 8, 13, 190, 189`. Which are: digits, digits in num pad, 'back', 'enter', '.', '-' – fguillen Mar 02 '15 at 18:38
  • Also we have to take care of the double dots like "10..34" which would make the number field to fail again. I'm editing the original answer with all these suggestions – fguillen Mar 02 '15 at 18:42
  • On Chrome 41 if you change the input type from number to text it clears the value preventing you from do a "quick cast" – Aaron Sherman Mar 12 '15 at 20:52
  • I think testing the keycodes will not prevent someone copy pasting bad characters into the field – James Aug 18 '15 at 09:03
  • @James key combination (paste, select all, etc) are also prevented. Tested on chrome and safari – Vizz85 Jan 29 '19 at 09:21
2

A way to control input number is to set it empty on blur when you can't read value

static formattedDecimalInput(input, maxScale, allowEmpty = true) {
    input = $(input);

    input.on("blur", function(e) {
        var inputVal = input.val();

        if(inputVal != "" || !allowEmpty) {
            if(inputVal == "") {
                inputVal = "0";
            }
            var number = Number(inputVal);
            input.val(number.toFixed(maxScale));    
        } else {
            input.val("");
        }
    });
}

You can formatted it by the way, and if you have invalid char on server side you can send a bad request response.

If you want a requiered field, you can just check if the input is empty with javascript before your server call

It is not really the answer of the initial question but I was looking for a user friendly control for this type of input when I arrived here

Vincent
  • 56
  • 3
1

My hack for this problem includes the following (i use jQuery validators):

    $(document).on('keyup', '[type="number"]', function () {
        if (this.validity.badInput) {
            $(this).attr('data-badinput', true);
        }
    });

Later in validator method i do this:

    $.validator.addMethod('isInteger', function (value, element, parameterValue) {
        if ($(element).attr('data-badinput')) {
            //We know nasty browser always clears incorrect input, so empty string will look OK next time
            $(element).removeAttr('data-badinput');
            return false;
        }
        return !value || /^-?\d+$/.test(value);
    });
Alexander
  • 1,152
  • 1
  • 16
  • 18
0

You're setting a numeric input field to a string which is not a number. What did you expect to happen? The whole point is that these fields don't allow or accept non-numeric input. They are documented as only accepting a floating point value.

There is no "hack" available or required; the solution is to stop using a number input field for a value that isn't a number. Credit cards, phone numbers, etc; these things are not numbers. They contain digits as a subset of the valid characters, but they also contain completely non-numeric characters like spaces, hyphens and parenthesis. They need to be stored and treated as regular strings.

Use <input type="text"/>.

user229044
  • 232,980
  • 40
  • 330
  • 338
  • 8
    If I'm so crazy the why does Firefox preserve it as a string? That seems the most inclusive/safest default behavior. Also the `type=number` is better for mobile devices b/c it pulls up number pad. I have to respectfully disagree on this one. – tim peterson Sep 07 '13 at 20:10
  • 2
    you can set the inputmode (html5) attribute for an input field to 'numeric'. that might give you the number pad – sdeburca Sep 07 '13 at 20:13
  • Mobile device usability is rate-limiting. Think Webkit has it wrong. – tim peterson Sep 07 '13 at 20:13
  • @timpeterson Not according to the specifications. You can respectfully disagree all you want, but, respectfully, that just makes you wrong too. – user229044 Sep 07 '13 at 20:14
  • @meagar, -@sdeburca may have solved the debate if `inputmode='numeric'` is respected by Webkit – tim peterson Sep 07 '13 at 20:17
  • @meagar , -@sdeburca: Just checked, `inputmode='numeric'` isn't respected my mobile safari. I still much rather not annoy 99% of the world by making them click an extra button to reach the numberpad (not to mention, failing validation with often cryptic or in this case without an error message) rather than point out to them that "123-123" is in fact not a number. – tim peterson Sep 07 '13 at 20:32
  • @timpeterson That's the same question. You just linked to this same page. – user229044 Sep 08 '13 at 03:38
  • related SO thread: http://stackoverflow.com/questions/8222528/ios5-show-numeric-keypad-by-default-without-using-type-number-or-type-tel?rq=1 – tim peterson Sep 08 '13 at 19:07
  • 14
    `What did you expect to happen?` `valueAsNumber` returns `NaN`, which makes sense. `value` returns an empty string, which does not allow me to add relaxation to the constraints, such as removing the spaces, normalizing the use of `.` or `,` for decimal separator... – njzk2 May 27 '14 at 19:14
  • I fully agree with @njzk2. My problem is that even with only allowing certain keys, you can still type `--3..1.`. With no way to access that invalid input and correct it, you are stuck preventing invalid inputs. But if you tell it "only allow `.-` if there isn't already `.-` in the field", then if the user highlights the number and tries to type `.` or `-` over it, they can't, and I can't correct for that because type=number doesn't have selectionStart or selectionEnd. So far, this thing is more trouble than it's worth. – miyasudokoro Oct 13 '14 at 15:49
  • The behaviour of `value` causes another problem : a plugin like autoGrowInput (https://github.com/Pixabay/jQuery-autoGrowInput) can't work with – yolenoyer Sep 29 '15 at 11:29
  • 3
    `What did you expect to happen?` - I expect that if i enter text instead of number in this field - if this is allowed - on form submit the text is not cleared and i see i enter wrong thing. Currently, my numeric field, that allows empty values, is successfully submitted AUTOMATICALLY after clearing alpha characters from numeric field. This is INCORRECT behavior (seen at least in Firefox). – Alexander Oct 23 '15 at 13:20
  • 4
    What did you expect to happen? Well, I expected to be able to detect the difference between an empty field and a field with garbage so I can tell the user what to fix. Telling the user "The numeric field cannot be empty" when it has non-numeric data makes me look stupid. I want to tell them "Please enter only numeric data in the numeric field." – David Rector Nov 10 '17 at 20:50
  • fyi chrome alows `eeee` as an valid input but returns "" (empty string) for the input `value` – Matthieu Riegler Sep 25 '18 at 16:41