Safari on iOS allows you to pull a specific keyboard for an input field. For example if I have a field expecting numeric input, we’ll make sure that our input has the attribute of “number” rather than the usual “text” as such:
<input type="number"/>
This will save users a few clicks; however Safari forces input validation on the client-side when you do that. Meaning if you wanted a numeric keyboard by default while allowing other characters, you input will fail.
Not only is it highlighted in red, this.value also returns null as opposed to what is clearly in the field, rendering it unusable.
When the field is set to “-10”
When the field is set to “+10”
One would think that explicitly defining a pattern to check for would let Safari know that we are interested in trumping its input validation but such is not the case. As a result, the following does not help our cause:
<input type="number" pattern="(-+){0,1}[0-9]{1,}">
So here’s a completely hackish way to get the keyboard you want with no input validation:
<input type="number" pattern="(-+){0,1}[0-9]{1,}" onFocus="that=this; setTimeout(function(){ that.setAttribute('type','text'); },10);" onBlur="that=this; setTimeout(function(){ that.setAttribute('type','number'); },10);"/>;
That’s right, after iOS pulled the right keyboard, we change the field type to “text”. Note that the client will still display some red around the field as it will perform the validation but at least this.value will return what’s in the friggin’ field.
Note 1: the setTimeout is necessary, if we perform the change immediately onFocus, safari pulls the text keyboard.
Note 2: the that=this indirection is necessary to save a reference of the object to the context of setTimeout.