HTML5 input type=number value is empty in Webkit if has spaces or non-numeric characters?
Asked Answered
T

6

32

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?

Troubadour answered 7/9, 2013 at 19:56 Comment(0)
T
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/

Troubadour answered 7/9, 2013 at 22:11 Comment(3)
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)Overpraise
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.Troubadour
What about accessibility? Doesn't this prove to be troublesome for screenreaders?Benempt
S
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.

Subgroup answered 8/9, 2013 at 4:14 Comment(7)
I would add codes 97-106 (numpad numbers) to the allowed list too.Fiddling
The event wall described here is the best workaround I've found so farIvonne
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', '.', '-'Ivonne
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 suggestionsIvonne
On Chrome 41 if you change the input type from number to text it clears the value preventing you from do a "quick cast"Locality
I think testing the keycodes will not prevent someone copy pasting bad characters into the fieldPilar
@Pilar key combination (paste, select all, etc) are also prevented. Tested on chrome and safariLingam
B
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

Biogeochemistry answered 5/10, 2018 at 0:53 Comment(0)
S
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);
    });
Samsara answered 23/10, 2015 at 13:28 Comment(0)
F
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"/>.

Fremd answered 7/9, 2013 at 20:5 Comment(14)
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.Troubadour
you can set the inputmode (html5) attribute for an input field to 'numeric'. that might give you the number padNationalize
Mobile device usability is rate-limiting. Think Webkit has it wrong.Troubadour
@timpeterson Not according to the specifications. You can respectfully disagree all you want, but, respectfully, that just makes you wrong too.Fremd
@meagar, -@Nationalize may have solved the debate if inputmode='numeric' is respected by WebkitTroubadour
@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.Troubadour
@timpeterson That's the same question. You just linked to this same page.Fremd
related SO thread: #8223028Troubadour
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...Lie
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.Elegant
The behaviour of value causes another problem : a plugin like autoGrowInput (github.com/Pixabay/jQuery-autoGrowInput) can't work with <input type="number">Surplice
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).Samsara
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."Berte
fyi chrome alows eeee as an valid input but returns "" (empty string) for the input valueGoof
S
0

In case anyone finds this like me, I've solved this issue using reportValidity

I wanted to report a different message to the user if the imput was empty or just had invalid characters...

<input id="num" type="number" />

<script>
    let fieldElement = document.getElementById('num');
    let fieldValue = fieldElement.value;
    let htmlValid = fieldElement.reportValidity();
    
    let error = '';
    if (fieldValue == '' && htmlValid) {
        error = 'Value missing';
    }
    if (fieldValue == '' && !htmlValid) {
        error = 'Value incorrect';
    }
</script>

https://jsfiddle.net/bt063157/

Sash answered 8/11, 2023 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.