Is there an acceptable cross-platform method for displaying a numeric keypad in standard web forms on a touch-based device?
Asked Answered
N

1

7

The goal: To find a cross-platform solution for displaying numeric keyboards on mobile touch-based devices, with a minimum of hacks.

The problem:

I have a regular web application using data input forms, containing primarily numeric data. When a user interacts with my site on a mobile device, I would like to display a numeric virtual keypad as most standard keyboards require a second press to switch from alphas to numbers. I know that i can trigger different keyboard by setting the "type" attribute of input element:

type=number: This works great under iOS/Safari. I am unsure about other browsers on the platform.

On Android, this does not consistently raise the correct keyboard on various browsers and often results in unwanted elevator buttons on the input. I have yet to find a clean way to turn these off in CSS.

type=tel: This almost works on iOS/Safari, but the telephone keyboard lacks a decimal button.

Seems to work great across multiple android browsers, without any extraneous UI elements added to the page.

My current solution is hacky and simplistic. Based on a class that I'm already using for numeric validation, I replace each text element that should contain a number with a new input that is either a number or a tel type based on the detected OS/browser.

var isAndroid = navigator.userAgent.match(/android/i) ? true : false;
var isIOS = navigator.userAgent.match(/(ipod|ipad|iphone)/i) ? true : false;

if (isAndroid || isIOS) {
    var useNumberType = (isIOS ? true : false); //iOS uses type=number, everyone else uses type=tel
    jQuery("input.num").each(function () {
        var type = (useNumberType ? "number" : "tel");
        var html = this.outerHTML;
        html = html.replace(/(type=\"?)text(\"?)/, "$1" + type + "$2");
        this.outerHTML = html;
    });
}

I would prefer to not use browser detection and to not change out the inputs on the fly at run time. I could possibly introduce an http module on the server side that did basically the same thing, but that is not substantially better. I'm shocked that there isn't a CSS call for this.

Is there a better way to get a numeric keyboard with a decimal button, that works on all or most touch-based mobile devices without adding weird UI elements to the page?

-------------- update

I don't think there is a way to do what I really want to do, which is to setup a single input style or type that will work well across desktop browsers and all major mobile touch-based platforms. I settled on changing the type of the input through a direct DOM call rather through jQuery instead of rewriting the entire input via outerHTML. I suspect there isn't much difference in effect, but the code is a little cleaner. Since I'm not changing input types on the desktop, I shouldn't have to worry about IE's read only restriction on the attribute.

Ideally, I'd probably handle this on the server side so everything got sent to the browser in the format desired for the device making the request. But for now the new code looks more like this:

var isAndroid = navigator.userAgent.match(/android/i) || navigator.platform.match(/android/i) ? true : false;
var isIOS = navigator.userAgent.match(/(ipod|ipad|iphone)/i) ? true : false;

if (isAndroid || isIOS) {
    var useNumberType = (isIOS ? true : false); //iOS uses type=number, everyone else uses type=tel
    jQuery("input.num").each(function () {
        var type = (useNumberType ? "number" : "tel");
        if (this.type == "text") {
            this.type = type;
        }
    });
}
Narceine answered 21/5, 2012 at 21:37 Comment(3)
Does your page use a mobile framework?Mattingly
Does it also have to work non-mobile?Decided
Ideally, yes, it should work on non-mobile browsers as well. Which is why i'm detecting the platform before making any changes to the page. I am not currently using a mobile framework. It's an adaptation of our regular site to improve performance for mobile browsers. In the future, when there's more money, we may be able to go back and write a mobile-only site.Narceine
V
2

Protip: when working with mobile, do NOT interfere with the user experience. This means keeping the built-in keypads as they are.

Some users may even have Javascript disabled on their mobile devices/browsers!

What you should do here is include an HTML hint to the browser. This way, mobile browsers should know what kind of content they are interacting with.

HTML5 includes several new <input> content types that should be supported on all modern mobile devices (and most modern browsers)

You can find the full list here.

What you want specifically is the following:

Old code:

Phone number: <input type="text" name="phone" />

New code:

Phone number: <input type="tel" name="phone" />

I don't know that any browsers currently support "tel", so you could use something like the following:

Phone number: <input type="number" name="phone" min="1000000000" max="9999999999" />

This is a bit of a hack, but is another option for you.

This is a MUCH simpler and more maintainable way of doing things, and better for the user.

Please let me know if you have any questions. I know this isn't directly answering the question, but it is a better way of doing things for now, in my opinion. :)

EDIT:

A possible way to get around this for each browser is by checking the user agent using JS/Jquery. I'm not sure exactly how to do this, but here is a tutorial on how to do so in .NET and changing the CSS for each element using JQuery.

EDIT EDIT!:

Try just modifying your code as such:

var isAndroid = navigator.userAgent.match(/android/i) ? true : false;
var isIOS = navigator.userAgent.match(/(ipod|ipad|iphone)/i) ? true : false;

if(isIOS)
    $(.phoneInput).attr("type", "tel");
if(isAndroid)
{
    $(.phoneInput).attr("type", "number");
    $(.phoneInput).attr("min", "1000000000");
    $(.phoneInput).attr("max", "9999999999");
}

I hope this out of everything works! You might have to switch the two if statements, depending on how your testing turns out.

Vaulted answered 21/5, 2012 at 22:53 Comment(10)
Thanks taking the time to respond. That's actually what the javascript above does. Unfortunately, I'm forced to make a device specific choice between type=number and type=tel because of rendering problems on iPhones vs. Android. I'm making the change on the fly rather than the html because it also has to render in desktop browsers without doing anything weird. I was hoping to get around one or both of those things, maybe by applying some magic CSS or input Attributes that I haven't been able to find.Narceine
Perhaps you could use CSS? Take a look above in a moment.Vaulted
You're right about javacript, of course, but in this case, someone "more in charge" than me has decided we're not supporting a no javascript user in our application. Since a whole lot more would break than this, if javascript were disabled, it's not a relevant use case for this application.Narceine
protip: read up on unobtrusive javascript. It's my current favorite design methodology, and it has enough business value for you to attempt to propose it in the future to your "more in charge" people :)Vaulted
Unfortunately, in most browsers, you cannot modify the type attribute of an input after it has been rendered to the page. That's why i'm re-rendering the entire input again using outerHTML, instead. Like you I would prefer a CSS solution, but i've been unable to locate any CSS that will affect the keypad selected. I'm considering setting everything to type=number and using CSS to hide the ugly elevator buttons. The CSS for hiding those buttons does not seem to be universal, though and it won't help browsers like Opera on Android where type=number is currently ignored.Narceine
Are you using jQuery? The last thing I suggested should work great to change the elements after they've been rendered. That's the whole point of jQueryVaulted
yes. I'm using jQuery. When I tried this I got very specific errors reporting that it was not possible to update the type attribute. That may have just been Opera, but it broke the remainder of the script rendering.Narceine
Yes, that might be the case. Take a gander: #1544817Vaulted
Thanks for encouraging me to look further at modifying the type attribute. I hope that some day, all the browsers start handling all these html 5 tags the same way and introduce some better CSS for handling their UI. +credit for your effort.Narceine
Thanks, hopefully you figure something out. :Vaulted

© 2022 - 2024 — McMap. All rights reserved.