Mottie / Keyboard

Virtual Keyboard using jQuery ~
http://mottie.github.io/Keyboard/
Other
1.78k stars 723 forks source link

How to suppress mobile browser keyboard #204

Closed bizcad closed 11 years ago

bizcad commented 11 years ago

When applying Mottie Keyboard to a mobile device, on Android at least, a click on the text input brings up the Mottie Keyboard, but also the Android keyboard. I want to not show the android keyboard. I have tried the blur hack as discussed here but it does not work.

Following is my ko.bindingHandler init where the keyboard is bound to the text element. I am trying to just show a number pad so I filter viewModel items not decimal or integer.

window.ko.bindingHandlers.SetInputType = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {        
        // the viewModel has a data variable called dataColumnType which indicates
        // what type of input element it is.  The if statement does not bind
        // mottie to text fields.
        if (viewModel.dataColumnType() === 'decimal' || viewModel.dataColumnType() === 'integer') {
            //    var marker = $('').insertBefore($el);
            //    $($el).detach().attr('type', 'number').insertAfter(marker);
            //    marker.remove();
            if (!isNaN(app.vm.reading.reading().value())) {
                $(element).filter(':input:focus').blur();
                $(element).keyboard({
                    layout: 'custom',
                    display: {
                        'deg': 'D:degrees', // degrees
                        'rad': 'R:radians', // radians
                        'grad': 'G:grads', // grads
                        '10x': '10\u207f',
                        '2pi': '2\u03c0',
                        'acos': 'cos\u207b\u00b9',
                        'acosh': 'cosh\u207b\u00b9',
                        'asin': 'sin\u207b\u00b9',
                        'asinh': 'sinh\u207b\u00b9',
                        'atan': 'tan\u207b\u00b9',
                        'atanh': 'tanh\u207b\u00b9',
                        'clear': 'CE',
                        'clearall': 'C',
                        'cuberoot': '\u221bx',
                        'equals': '=',
                        'invx': '1\u2044x', // replaced with an image
                        'm-': 'M-',
                        'mc': 'MC',
                        'meta1': 'Inv', // show inverse trig function keyset
                        'mplus': 'M+',
                        'mr': 'MR',
                        'ms': 'MS',
                        'pi': '\u03c0',
                        'sqrt': '\u221a',
                        'x2': 'x\u00b2',
                        'x3': 'x\u00b3',
                        'xy': 'xy',
                        'yroot': 'yroot' // replaced with an image
                    },
                    customLayout: {
                        'default': [                            
                        ' ( ) {sign} {b}',
                        ' 7 8 9 /',
                        ' 4 5 6 *',
                        ' 1 2 3 -',
                        ' 0 {dec} +',
                        ' {c} {a}  {equals} {clear}'
                        ],
                        'meta1': [
                        ' ( ) {sign} {b}',
                        ' 7 8 9 /',
                        ' 4 5 6 *',
                        ' 1 2 3 -',
                        ' 0 {dec} +',
                        ' {c} {a}  {equals} {clear}'
                        ]
                    },

                    // Turning restrictInput on (true), prevents yroot and but it
                    restrictInput: true,  // Prevent keys not in the displayed keyboard from being typed in
                    useCombos: false, // don't want A+E to become a ligature
                    wheelMessage: '',    // clear tooltips

                    // set up degree/radian/grads mode
                    visible: function (e, kb, el) { // e = event, kb = keyboard object, el = original input
                        var mode = kb.mode || 0, sel = '.ui-keyboard-';
                        sel += (mode === 1) ? 'deg' : (mode === 2) ? 'grad' : 'rad';
                        kb.$keyboard.find(sel).addClass(kb.options.css.buttonAction);
                    },

                    // multiple parameter functions highlight when first parameter is saved,
                    // this makes sure the buttons aren't highlighted when the memory storage clears.
                    change: function (e, kb, el) {
                        if (kb.memory2 === '') {
                            kb.$keyboard.find('.ui-keyboard-xy, .ui-keyboard-yroot').removeClass(kb.options.css.buttonAction);
                        }
                    }

                }).addTyping();

                // the blur hack.
                element.setAttribute('readonly', 'readonly'); // Force keyboard to hide on input field.
                element.setAttribute('disabled', 'true'); // Force keyboard to hide on textarea field.
                setTimeout(function () {
                    element.blur();
                    // Remove readonly attribute after keyboard is hidden.
                    element.removeAttribute('readonly');
                    element.removeAttribute('disabled');
                }, 100);
            }
        }
        $(element).change(function () {
            var val = element.value;
            // posts the typed value back to the viewModel
            window.app.dataservice.setReadingValueForMRDId(viewModel, val);            
        });

        // dynamically add an id to the element for later reference.
        element.id = 'readinginput' + app.vm.reading.reading().id();

    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
      // does nothing.
    }
};
Mottie commented 11 years ago

I still haven't found a good solution. So far the only thing I've found that might work is using phonegap and adding some java (not javascript) to make it work. Sadly, I won't be able to do anything until I get back from my sabbatical.

Mottie commented 11 years ago

Ok, I finally got my hands on an Android tablet, and I think I found a solution... but there's a catch.

You can either just set the readonly attribute of the input to prevent the default keyboard from opening, BUT if you have an attached or wireless keyboard, it won't work.

<input type="text" readonly="readonly">

Or, you can set the lockInput option to true... in this example I ended up detecting the userAgent string to determine if the user is on an android, iPad, or iPhone. It's not the best solution, but it should work for now.

$(function(){
  $('#keyboard').keyboard({
    lockInput : navigator.userAgent.toLowerCase().search(/ipad|iphone|android/i) > -1
  });
});

I think I'm going to add a new keyboard key that allows you to switch the readonly attribute. That way the user has control of when to lock or unlock the manual keyboard input... but I'm sure the build-in keyboard will pop up in that case =(.

bizcad commented 11 years ago

Great news. I will give it a try. I do not know why I did not think of the readonly before. That was a headslap moment for me. The whole point of my app is to use the tablet without a kb/mouse so there is no catch for me. I do not need to worry about the user agent string because I have control over the device.

As an interim solution I downloaded Perfect Keyboard Free from the Android App store and was able to set the input to the keypad in their settings. I just needed to get the page (it is a Single Page App) into some tester's hands. The Mottie KB is better because I can add calculator functions into the javascript.

Ultimately, I thought I could make an android app that has the Web Page part as it's only activity. The web page would go to my regular web site. I think this is more or less what phonegap does. Then I could write some functionality that would post from the javascript to the app to set the KB off.

All in all, I am very pleased and surprised at your responsiveness. I cannot thank you enough for paying this much attention to me.

Nick Stein aka bizcad

ayushranjan-planetria commented 9 years ago

Hi @Mottie , I am unable to suppress the native keyboard on iPad, I have tried with lockInput:true, but it doesn't work. I tested the demo you shared "http://jsbin.com/eniQaBO/3/" on my iPad but the native keyboard also appears along with the mottie keyboard. I also tried with readonly="readonly" and hacked the reveal() method by commenting these lines

/*if (base.$el.is(':disabled') || (base.$el.attr('readonly') &&
            !base.$el.hasClass(kbcss.locked))) {
            base.$el.addClass(kbcss.noKeyboard);
            return;
        } else {
            base.$el.removeClass(kbcss.noKeyboard);
        }*/

this works for the first time but as we start pressing the keyboard buttons, the iPad keyboard appears from nowhere. Can you please look into it? Tested on iPad 2 (ios v8.3)