Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

the virtual keyboard renders slowly because of the hardware, and how can I accelerate it? #217

Closed
webgldawn opened this issue Nov 7, 2013 · 18 comments

Comments

@webgldawn
Copy link

a text box binds the keyboard event,when focusing on the text box, the responsing time is very long. I think because of the allocation of my computer hardware is low, the rendering of virtual keyboard is slow. Now I want to konw that, could I render the virtual keyboard in the initialization of the page,not when focusing on the text box? and how can i do it?
thanks!

@Mottie
Copy link
Owner

Mottie commented Nov 7, 2013

Hi @webgldawn!

The rendering is based off of more than just hardware, it also depends on the browser you're using. At this time, Chrome (maybe Maxthon) is the fastest browser.

Anyway, to build the keyboard before the user clicks on it, do this (demo):

$(function(){
  $('#keyboard')
    .keyboard() 
    // activate the typing extension
    .addTyping();
});
$(window).load(function(){
  // initialize keyboard so it doesn't need to render
  // when you click on the input
  $('#keyboard').data('keyboard').startup();
});

Basically the code within the $(window).load function builds the keyboard after the web page has completed loading, so hopefully in the time it takes for you to move your mouse, the keyboard will be done rendering.

The original keyboard used to do this, but when you have ten keyboards on the page, there was a noticeable lag.

@BrandonLWhite
Copy link
Contributor

Thanks for the tip. This helps on my low-performance ARM-based embedded system where there was noticeable FlashOfUnstyledContent (FOUC) the first time the keyboard is shown. I'm going to try combining .startup() with using a single keyboard to service all inputs.

[RETRACTION: I was mistaken. My issue with FOUC stems from the jQuery Mobile extension and the 10ms delay before visible.keyboard is fired. Also, after investigation it does not appear to be feasible at this time to utilize a single keyboard DOM element to service all inputs.]

@ghost
Copy link

ghost commented Feb 7, 2014

I have the same impression on Intel Atom based tablets running Windows 8, it doesn't show up as fast as it does on my desktop, just by adding the that startup() function on the page load will do the trick?

@ghost
Copy link

ghost commented Feb 7, 2014

also, if I have 20 controls using the same layout do I need to preload all of them?

@Mottie
Copy link
Owner

Mottie commented Feb 7, 2014

Hi @paul-c-f!

Sadly, the current version of the keyboard does indeed build a new keyboard for each input. Someday when I have the time, I want to have just one keyboard built per layout - @pascal-bach added a singleton option (see #83) which might solve the problem. And honestly, I just haven't had the time to integrate and/or refine those changes.

@BrandonLWhite
Copy link
Contributor

@Mottie I agree, I think that would be ideal. I have some code I wrote today that destroys the keyboard whenever it is hidden. This way my DOM doesn't accumulate a bunch of keyboards. But alas, on my industrial HMI device doing it this way introduces noticeable latency when the user touches the input (because the keyboard is now always created each time). For now it is acceptable, but eventually I'm going to need to speed this up.

It does seem that if multiple inputs could reuse a keyboard, it would solve both problems (element accumulation and latency). I was prepared to attempt that today, but after diving in it is clear that it's a much bigger change than I expected.

FYI -- For my application I'd actually have 2 possible keyboards - a custom numeric keypad, and the other a conventional QWERTY.

@Mottie
Copy link
Owner

Mottie commented Feb 8, 2014

Yeah, it's a much bigger change than I have time for right now. Maybe I could just have a "pre-built" conventional QWERTY keyboard set up. I think that would pretty much bypass the rendering step for that particular keyboard.

@Mottie
Copy link
Owner

Mottie commented Feb 8, 2014

Here is an example (demo):

$('#keyboard')
    .on('initialized.keyboard', function (event, keyboard, $el) {
        if (keyboard.options.layout === "qwerty") {
            // this assumes the original element is an input
            // And usePreview is true
            keyboard.$keyboard = $('.qwerty-prebuilt-usePreview');
            keyboard.$preview = $keyboard.find('.ui-keyboard-preview');
        }
    })
    .keyboard({
        layout: 'qwerty'
    });

I copied the HTML directly from the Chrome Dev Tools window (right-click on the table after it renders, and "Copy as HTML")

This method might even solve the issue you were having with jQuery Mobile.


Ugh, nevermind, this method WON'T WORK because some variables are populated as the keyboard is being built; so lockInput won't work, mapped keys, keyboard navigation extension, etc....

Mottie added a commit that referenced this issue Feb 8, 2014
@Mottie
Copy link
Owner

Mottie commented Feb 8, 2014

Hey @BrandonLWhite!

My OCD kicked in and I think I have something usable pushed out to the "working" branch. I haven't had a chance to thoroughly test the changes, so I was hoping you could help me by testing the changes, at least on mobile.

This change:

  • Builds a keyboard when it becomes visible (same as before)
  • Instead of saving the layout only to the specific input, it saves it to $.keyboard.builtLayout, so the built layout for the qwerty would be located at $.keyboard.builtLayout.qwerty but only if it is undefined.
  • It then makes a clone of that keyboard and uses it.
  • Any additional inputs with attached keyboards will now just clone the originally built layout.

I made it clone the keyboard because it would be possible to have multiple keyboards open at once, depending on the settings.

So, in your situation, the start up function $('#keyboard').data('keyboard').startup(); would still need to be called to initially build the keyboard. And as you stated that you need to remove the keyboards to save memory, this should no longer cause rendering issues each time the user focuses on an input.

@BrandonLWhite
Copy link
Contributor

This is starting to come along and looks to be promising. Here are a few additional issues I've noticed:

  • After the initial showing, jquery mobile styles are not applied to the action keys.
  • Since buildLayout is indexed by the layout name (eg "custom") this basically prevents you from having multiple custom layouts on a page (which I intend to do in my application). We probably need a way to extend the custom names, such as "custom-keypad", "custom-foo". Or possibly better, just make it so that any layout name that is not one of the built-ins is treated as a custom.

@Mottie
Copy link
Owner

Mottie commented Feb 11, 2014

The easiest method to add multiple custom keyboards would be to just extend $.keyboard.layouts:

$.keyboard.layouts["my-custom-layout"] = {
    'default' : [
        '= ( ) {b}',
        '{clear} / * -',
        '7 8 9 +',
        '4 5 6 {sign}',
        '1 2 3 %',
        '0 . {a} {c}'
    ]
};

$(function(){
    $('#keyboard').keyboard({
        layout: "my-custom-layout",
        usePreview: false
        })
    });
});

@BrandonLWhite
Copy link
Contributor

Excellent!

@Mottie
Copy link
Owner

Mottie commented Feb 18, 2014

Please download the latest version, it only builds a keyboard once per layout and adds or removes the keyboard from the DOM and memory when not visible to make this plugin much more mobile friendly.

Thanks for your patience!

@Mottie
Copy link
Owner

Mottie commented Mar 6, 2014

I'm guessing this issue has been resolved, so I'm going to close it. If you continue to have problems, please feel free to continue this discussion.

@Mottie Mottie closed this as completed Mar 6, 2014
@pixelfreak
Copy link

Hi @Mottie

My use case is somewhat different and I'm wondering if there is a workaround.

I have multiple inputs and I want the keyboard to always be visible even if the focus is no longer on the inputs. If I use alwaysOpen or stayOpen, I'll see multiple keyboards.

Is this doable?

Thanks!

@Mottie
Copy link
Owner

Mottie commented Apr 12, 2015

Hi @pixelfreak!

The way the plugin is set up, it makes an instance of the keyboard for each input/textarea. So, you can't attach one keyboard to multiple elements.

What might work is if you stack the keyboard so it looks like there is only one.

@pixelfreak
Copy link

I've stacked them and it works fine, the only thing missing is when focus is gone from any of the textbox, the keyboard disappears. I guess it's a limitation I'll have to deal with. Thanks

@Mottie
Copy link
Owner

Mottie commented Apr 12, 2015

It should not disappear when alwaysOpen is set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants