How to listen for keyboard open/close in Javascript/Sencha?
Asked Answered
C

7

21

I have a HTML5/Javascript (Sencha) app that I have packed into PhoneGap for iOS in XCode. One way or another, I want to be able to listen for the keyboard open/close events and do something accordingly. Is there any way to do this?

Crin answered 23/11, 2011 at 11:35 Comment(5)
Keyboard will be automatically invoked while you are focusing textfield, textareafield ... . So you can create listener to the focus event in javascript.Tut
Then, I also want to listen for when textfields etc. lose focus, is there an event for that?Crin
I think you can use the blur eventTut
It worked. If you wanna go ahead and post an actual answer I'll give you the check.Crin
Happy to hear that... I will post it as answer.Tut
T
23

Keyboard will be automatically invoked while you are focusing textfield, textareafield ... . So you can create listener to the focus event in javascript which is similar to listening to the keyboard open event. Also you can use the blur listener to handle the keyboard close.

Thanks.

Tut answered 23/11, 2011 at 12:49 Comment(4)
I am using this to setfocus. inpMessage.fieldEl.dom.focus(); its work fine in chrome not in the device.Sticky
note that this will fire before the keyboard has animated open, so it can be too early if you need to make positioning/layout adjustmentsMadox
You need to do more test before posting your answers. When you tap on back button of Android device keyboard will be hidden but it won't trigger blur event.Mcclimans
@devmaniac ... thanks for your feedback. I am not saying hiding keyboard will invoke the blur event. If we call blur to a textfield, which is currently focused, it will hide the keyboard. Its just the opposite. :)Tut
W
16

Recently I got stuck in a similar problem. After some research, I realized that 'Visual viewport Api' was the solution.

'The visual viewport is the visual portion of a screen excluding on-screen keyboards, areas outside of a pinch-zoom area, or any other on-screen artifact that doesn't scale with the dimensions of a page'

https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API

window.visualViewport.addEventListener('resize', event => console.log(event.target));

Code above will be executed every time the 'visual viewport' is resized, for instance, when the keyboard opens/closes.

Woolfell answered 1/12, 2020 at 14:44 Comment(2)
I think this is the best answer because it allows you to avoid tightly coupling this functionality to the native layer integration. So, if this app gets moved off of PhoneGap and into web only, React Native, or a native web view, then there would be no need to change the implementation.Zionism
This works perfectly. The proposed answer does not account for the time it takes for the keyboard to open, which can cause issues if you need to make changes following its appearance, such as scrolling to the input element.Cope
V
12

I've encountered the same issue, and I think that the best solution in your case is to use a PhoneGap plugin which will bind the native events, like this one :

https://github.com/driftyco/ionic-plugins-keyboard/tree/60b803617af49a10aff831099db90340e5bb654c

It works great on Android and iOS the same way, just bind those events:

window.addEventListener('native.showkeyboard', keyboardShowHandler);

window.addEventListener('native.hidekeyboard', keyboardHideHandler);
Vaas answered 19/6, 2014 at 9:42 Comment(2)
Will this work on browsers as well ? Because that library seems to be for CordovaBrenda
You need Phonegap/Cordova indeed (Caution, this answer is 7 years old)Vaas
C
4

Triggering open status is easy using onclick or onfocus event, but on closing keyboard onblur event is not fired (because cursor remains in input/textarea). So I found solution by detecting window height which is significantly changed on keyboard open/close.

It is working in modern browsers on Android and iOS too. Demo: http://jsfiddle.net/qu1ssabq/3/

If necessary you can improve my code for devices which do not support addEventListener or innerHeight - there are available alternatives on the Internet.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0, minimal-ui">
<title>Detect keyboard opened/closed event</title>
</head>
<body>

<textarea id="txta" onclick="xfocus()" onblur="xblur()"></textarea><br>

<span id="status" style="background: yellow; width: auto;">closed</span>

<script type="text/javascript">
  function xfocus() {
    setTimeout(function() {
      height_old = window.innerHeight;
      window.addEventListener('resize', xresize);
      document.getElementById('status').innerHTML = 'opened'; // do something instead this
    }, 500);
  }
  function xresize() {
    height_new = window.innerHeight;
    var diff = Math.abs(height_old - height_new);
    var perc = Math.round((diff / height_old) * 100);
    if (perc > 50)
      xblur();
  }
  function xblur() {
    window.removeEventListener('resize', xresize);
    document.getElementById('status').innerHTML = 'closed'; // do something instead this
  }
</script>

</body>
</html>
Circumstantiality answered 17/12, 2014 at 15:4 Comment(0)
D
3

As suggested by camiloHimura's answer, you can make use of window.visualViewport.

The visual viewport is the visual portion of a screen excluding on-screen keyboards, areas outside of a pinch-zoom area, or any other on-screen artifact that doesn't scale with the dimensions of a page.

I measured the difference between window.screen.height and window.visualViewport.height on several devices with the keyboard open and it is always more than 300px.

So you can do something like this:

const listener = () => {
  const MIN_KEYBOARD_HEIGHT = 300 // N.B.! this might not always be correct
    
  const isMobile = window.innerWidth < 768
  const isKeyboardOpen = isMobile 
    && window.screen.height - MIN_KEYBOARD_HEIGHT > window.visualViewport.height
}

window.visualViewport.addEventListener('resize', listener)

You should keep in mind that this solution might not work in all cases because it relies heavily on the assumption that the height of all devices' keyboards is approximately the same. Of course, you can tweak the hard-coded value but, as you can see, this is not a bulletproof solution.

Disyllable answered 10/2, 2021 at 15:20 Comment(0)
L
2

Another potential (but very hacky) solution is to watch the window resize event. It won't work for all use-cases, but on smartphones it's not so common to resize the window, so resize events are likely to come from the keyboard opening. This code is untested, but it illustrates the general idea:

let fullWindowHeight = window.innerHeight;
let keyboardIsProbablyOpen = false;

window.addEventListener("resize", function() {
  if(window.innerHeight == fullWindowHeight) {
    keyboardIsProbablyOpen = false;
  } else if(window.innerHeight < fullWindowHeight*0.9) {
    keyboardIsProbablyOpen = true;
  }
});

Might be helpful to use alongside the focus/blur events to help (for example) detect the keyboard closing when the user presses the back button (as pointed out by @filipvkovic).

Lavinia answered 23/11, 2011 at 11:35 Comment(0)
C
1

As far as I can see this is only possible in the Android builds for PhoneGap, see the pull request here: https://github.com/phonegap/phonegap-android/issues/94.

The events are called hidekeyboard and showkeyboard. You might check whether they fire on iOS too.

Caoutchouc answered 23/11, 2011 at 11:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.