35

I have been thinking about this a while now, and I can't figure a way to deal with it. Is there any way to detect if the user uses a virtual (software) keyboard or a traditional (hardware) keyboard?

The new Windows Surface has its own keyboard in the cover, and for Android / iPad there are a ton of different bluetooth keyboards.

So, do any of you have any input about this?
I'm aiming for Android, IOS & Windows Tablet/Phone.


Motivation: (very subjective)

When developing web applications for tablet/smartphone I have come to the understanding that it's easier - in many situations - to use a JavaScript keyboard instead of the OS's software keyboard.

Lets say you want to enter a PIN code. Instead of having a keyboard filling half of the screen:

Software (OS) keyboard:

|----------------|
|    [ input]    |
|                |
|----------------|
|  1  2  3  4  5 |
|  6  7  8  9  0 |
|----------------|

JavaScript keyboard:

|----------------|
|    [ input]    |
|    | 1 2 3|    |
|    | 4 5 6|    |
|    |_7_8_9|    |
|                |
|                |
|----------------|

If you need to handle a lot of inputs, maybe you want to make an overlaying div with the inputs and use the software keyboard:

|----------------|
| P1 P2    P3 P4 |
| [inp 1][inp 2] |
|----------------|
|    KEYBOARD    |
|                |
|----------------|

But if the user has their own hardware keyboard, we want to make the edit inline in place.


I have been looking around SO and found this post: iPad Web App: Detect Virtual Keyboard Using JavaScript in Safari? ... but this seams to only work in IOS - not sure about browser.

Community
  • 1
  • 1
andlrc
  • 41,466
  • 13
  • 82
  • 108
  • 1
    may be this post can help you http://stackoverflow.com/questions/2593139/ipad-web-app-detect-virtual-keyboard-using-javascript-in-safari – rahul Nov 07 '12 at 13:21
  • 1
    Can I ask why does it matter? Just curious why. – epascarello Nov 07 '12 at 13:21
  • @rahul I have all ready seen it. thanks. – andlrc Nov 07 '12 at 13:23
  • @epascarello Something like that ^^ – andlrc Nov 07 '12 at 13:31
  • I would be very surprised if there is a cross browser/works everywhere/possibly even works anywhere mechanism for doing this. This is because Javascript in a browser is too high level and was not designed to care about it's underlying hardware, especially the types of HIDs in use. This may start to change eventually with the rise in popularity of mobile devices, but I wouldn't expect a reliable solution any time soon. You will notice that even the solution provided by the linked question relies on an ugly hack that damages user experience while it is processing. – DaveRandom Nov 07 '12 at 13:46
  • 4
    Personally I would take a different approach - for the example use case you give, I would block the focus event on the input and always display the JS keypad instead, while listening for keyboard events to capture number keys pressed. This means that on mobile devices the virtual keyboard should not be shown, and on PCs and other devices with a hardware keyboard the user will still be able to use it to enter the digits. – DaveRandom Nov 07 '12 at 13:48
  • Keyboard itself is driver level, no way you can determine that in javascript. However, certain browsers do extend the javascript "library" of functions to add functionality i.e. to read if an ipad is landscape of portrait oriented. If there is a way to do this, it will be a method where there is a check to see what browser is used (ie safari) and to then use the appropriate javascript function. – Damien Overeem Nov 07 '12 at 13:57
  • 3
    What about non-discrimination law compliance? Can this system handle input by dictation, mouse movement or by eye-tracker? – Anko Nov 11 '12 at 23:37
  • android's keyEvent has a property called 'FLAG_SOFT_KEYBOARD'. From the docs: "This mask is set if the key event was generated by a software keyboard." ref: http://developer.android.com/reference/android/view/KeyEvent.html – logic8 Nov 12 '12 at 23:49
  • 1
    I really don't think you should do this. The software keyboard is one of the most basic elements of any touch screen interface—users understand how it works, and it's tightly integrated into the accessibility features of the OS. No matter how well you do it, you won't get a keyboard that's more intuitive and accessible on all platforms than the existing software keyboard. – Jordan Gray Nov 14 '12 at 10:32
  • You won't be able to detect when a hardware keyboard (USB, Bluetooth, remote desktop) replaces the software one on a mobile device. Just leave it to the OS and use the HTML5 input types (all mobile devices read those, regardless of doctype). Nowadays mobile devices can become desktop replacements (dock with HDMI+keyboard+mouse). – Tiberiu-Ionuț Stan Nov 14 '12 at 16:37
  • In 2018, using WebAssembly, drawing everything (including virtual keyboard and text selection) in WebGL, using 2 phase text paste into an empty auto-closing text input element is **a must**. Mobile web is hopelessly broken. I highly recommend to stop using HTML and CSS for **mobile web** apps. – Brian Cannard Jun 09 '18 at 08:27

6 Answers6

22

I think the best approach would be to combine HTML5 form attributes with an optional virtual keyboard link.

HTML5 form attributes can be used to trigger different types of keyboards. For example, <input type="email">, <input type="number"> and <input type="tel"> will trigger the appropriate keyboard types on iOS (not sure about Android/WinPho/other, but I would imagine it does the same), allowing the user to input the data more easily.

If you want, you could additionally offer a button to trigger a custom numpad under the text field for older non-HTML5 compliant mobile browsers. Those will display the new HTML5 fields as standard text fields.

You can use browser sniffing to detect mobile browsers, but don't forget that those can still support things such as bluetooth keyboards. Sniffing additionally has the problem that it will almost certainly miss some browsers, and incorrectly detect others, thus you shouldn't rely on it solely.

Jani Hartikainen
  • 40,227
  • 10
  • 60
  • 82
  • I want to make a LaTeX virtual keyboard. You push buttons like "matrix", "integral", "double integral". Using the keyboard, I can choose the type of delimiter, etc. The keyboard is already big... on a mobile device, the virtual keyboard gets in the way. Maybe it's me... :-( – André Caldas Aug 03 '20 at 21:53
8

I don't think overriding default onscreen keyboard is a good idea, and I'd recommend going with what Jani suggested - virtual keyboards adapt too.

But I'm sure it is possible to detect most keyboards with the resize event paired with focus on the field or by monitoring window.innerHeight (or some other [a-z]*Height) and comparing value before and after field focus.

This is a weird case of feature detection, so it will need plenty of experimentation. I wouldn't do it if I were you.

naugtur
  • 16,479
  • 5
  • 65
  • 107
3

The most bullet prof solution that works across Chrome/Safari etc.. and on both Android and iOS as of 20-nov-2017 will be to detect a change in the height of a div that has a vh height units (viewport height)

Then on any blur/focus change of an input/textarea check if that div now has a height of 30% less (in pixels) than it used to have before that blur/focus event.

CSS:

#height-div{height: 10vh;}

jQuery:

$(document).ready(function() {
    var initialHeight = $("#height-div").height();//gives current height in pixels! We save it for later comparisons 
}

Now here is the magic:

$("input, textarea").focus(function(){
        setTimeout(function(){
            if((initialHeight*0.7) > $("#height-div").height()){//if the current viewport height is smaller than 70% of the original size, it means that the keyboard is up
                //ENTER YOUR LOGIC HERE
            }else if((initialHeight*0.7) < parent.$submit.height()){//if the current viewport height is larger than 70% of the original size, it means that the keyboard is down
            //ENTER YOUR LOGIC HERE
            }
        },500);
});

$("input, textarea").blur(function(){
        setTimeout(function(){
            if((initialHeight*0.7) > $("#height-div").height()){//if the current viewport height is smaller than 70% of the original size, it means that the keyboard is up
                //ENTER YOUR LOGIC HERE
            }else if((initialHeight*0.7) < parent.$submit.height()){//if the current viewport height is larger than 70% of the original size, it means that the keyboard is down
            //ENTER YOUR LOGIC HERE
            }
        },500);
});
TBE
  • 885
  • 1
  • 9
  • 29
  • 1
    30% is just a guess. Seems like a fragile approach. – adi518 Jan 28 '18 at 23:49
  • 2
    1. Keyboards on android device can be customized to be in various sizes. 2. User can rotate his phone. 3. User can use split-screen. Sadly, this approach is not bullet prof at all. – Kamil Bęben May 07 '19 at 22:06
1

It may not be detecting the keyboard. But I would try detecting if the user is on a mobile browser. Since the devices that have native virtual keyboards almost unanimously run on mobile browsers.

Here is a nice little script that uses jquery

If they aren't mobile present your standard input field.

If they are mobile do not display the input field (So they don't get the virtual keyboard), instead have a hidden field or list that gets updated with jquery when they click the buttons for your pinpad.

Malkus
  • 3,638
  • 2
  • 22
  • 39
  • I have a tablet with no keyboard running a nearly normal installation of Windows 7. I use the same browsers I would on a PC, so this wouldn't work for me. Nice catch though. – Kendall Frey Nov 16 '12 at 15:26
1

I came across a newer question the other day and a great answer that may help with your keyboard issue.

Time out on jquery hover (touch)

Essentially it uses a JQuery function that returns a boolean if it was able to create a touch event.

$(document).ready(function() {

    function hasTouch() {
        try {
           document.createEvent("TouchEvent");
           return true;
        } catch (e) {
           return false;
        }    
    }

    var touchPresent = hasTouch();
});
Community
  • 1
  • 1
Malkus
  • 3,638
  • 2
  • 22
  • 39
0

WURFL is a serverside framework that offers you a lot of information about the requesting device's capabilities. With wurfel in place, your application will able to serve the various devices / device groups with optimised output/markup.

One of the simpliest scenarious would be to distiguish between desktops, tables and smartphones.

The database (xml file) is updated regularly and official api's are available for java, php and .net

Lukas Winzenried
  • 1,869
  • 1
  • 14
  • 21