Debugging is thinking: the story of virtual keyboard bug in mobile Safari

Eugenia Zigisova
3 min readMar 31, 2019

I’m a junior web developer and I am learning a lot each day. One of the most fundamental things I learned is when you build features, you most probably introduce bugs. Therefore debugging has an important role in the developer’s job.

I would like to share a story about a little but quite annoying bug who lived in our chat web application on iOS Safari browser.

On mobile browser when clicking the submit button, the <textarea> field loses focus by default and the keyboard gets hidden. It’s quite annoying for the chat user to tap on the input field to make keyboard open again each time when sending multiple messages in a row. Having the keyboard always opened would be much better for user experience. We achieved it by implementing the following algorithm:

  1. prevent the default behavior of form submit an event,
  2. keep the <textarea> focused to prevent the keyboard from collapsing,
  3. get data from the <form> and send a text message,
  4. reset the form to clear the <textarea> field.

Unfortunately, the virtual keyboard suggestions kept the previous input in memory, so it suggested the wrong things. It happened only on iOS devices in mobile Safari.

This is our first implementation:

At that time I was reading “Eloquent JavaScript” and before starting fixing an issue was very inspired by this quote:

“This is where you must resist the urge to start making random changes to the code to see whether that makes it better. Instead, think. Analyze what is happening and come up with a theory of why it might be happening.”

Let’s try thinking!

Our goal is to make the keyboard suggestions be updated after each message submit. To solve it we need to understand why even after clearing the form, the virtual keyboard keeps saving the previous value.

There could be the following explanation: the keyboard by default saves all previous input values until it is closed. I liked this idea from the very beginning and stuck to it when googling for possible solutions like “update autocorrect after submitting on iOS Safari”. “Luckily” there were a couple of similar issues on stackoverflow.

One of the possible solutions was to remove focus from <textarea> and then focus it again. My plan was to make the keyboard disappear, so it could “forget” the previous input and show it again straight away. However, I figured out that Mobile Safari doesn’t allow you to open the virtual keyboard programmatically when you call focus() on the text input field. This is not a bug, but a feature, because they don’t want to annoy users with unexpected keyboard popup. The keyboard gets opened only on events which are triggered by user interaction.

However, our chat interface is part of webview which is opened from the native app. That means it was possible to add this line to the code of iOS app theWebView.keyboardDisplayRequiresUserAction = NO. But this is so hacky! Let’s not even try.

“Focus” hack didn’t work and I almost end up with just adding autocorrect="off" to <textarea> element. It would disable all keyboard suggestions.

The Final Solution

After putting console logs wherever possible I was sure that we really clear the form. So the keyboard has to store previous input somewhere else. The question is where?

Our ChatForm component is creating 2 instances this.textarea and this.form. By that, we allocate memory to store <form> and <textarea> elements along with their values. The keyboard addresses this memory which (for some reason) keeps the values and prevents auto-suggestions from updating.

The bug was fixed after removing DOM elements from the instances. Yay!

One may say it is a hack and against the concept of React and I totally agree.

My debugging experience showed that when you try to fix a bug, you may find a lot of hacky workarounds. That is great that you made it work, but you might have no idea why. Analyzing and understanding the problem does not always prevent you from a hacky solution, but it GIVES you an idea why!

Wish y’all happy debugging! :)

--

--