Skip to content
This repository has been archived by the owner on Mar 27, 2021. It is now read-only.

iOS Keyboard reopens with numberbad after loosing focus and closing keyboard #174

Closed
faebeee opened this issue Feb 22, 2018 · 26 comments
Closed
Assignees

Comments

@faebeee
Copy link

faebeee commented Feb 22, 2018

Summary

The keyboard reopens automatically while clicking around.

iOS 11.2.1
Chrome 64.0.3282.112
Safari

Other information

Steps to reproduce:
Can also be reproduced here: https://stripe.github.io/elements-examples/

  1. Click in the credit card number input field
  2. Fill in some numbers(Doesn't have to be valid or the complete number)
  3. Click outside the input box (Somewhere on the page, event if there is no elements there)
  4. Close keyboard with the Done or the X button
  5. Click somewhere and the keyboard reopens
@sylver
Copy link

sylver commented Mar 8, 2018

Same problem here.

This isn't link to this repository and its components since I don't use them, I did my own wrapper around the stripe.js script.
It seems something is keeping the focus once the card element got it. No way to get rid of it (blur() or unmount() function does not work, it keeps popping even if the parent component has been unmounted...

I confirm this is specific to Safari on iOS, I don't have the problem elsewhere.

I keep digging but some help from you guys would be great @michelle

Thanks

@sylver
Copy link

sylver commented Mar 8, 2018

More investigation :

  • If a blur() is triggered on the iframe (since it does not do it by itself) while it has the focus, the keyboard is correctly close and will remain close
  • If anything else is interacted with without dismissing the keyboard first while the iframe has still the focus, it will hang on it forever..

@sylver
Copy link

sylver commented Mar 8, 2018

I found this problem is already discussed in #161 with a (kind of) workaround from @asolove-stripe
I came to the same conclusion that the iframe with a different origin is messing up with the main app, and the fix should be in the Stripe.js script itself.

Why are you not fixing it ? This is basically making impossible to use your library on ALL iOS devices, it should be at least mentioned on the documentation page (https://stripe.com/docs/stripe-js) and in the readme of this repository. We should not have to dig in closed (unresolved) issues on github to eventually find something related.

EDIT:
@asolove-stripe your workaround on #161 only takes into account the submit of the form. But the keyboard stays open in any other case (ie. when a blur occurs, no matter why).

I'm using something a bit more twisted (not really a fan, but at least it works in every case) :

// With element being a reference to the card element created by stripe.elements()
// or the CardElement component.
element.addEventListener('blur', ev => {
  // Apply only as a workaround for Safari on iOS,
  // else it will create an infinite loop on the `blur` event.
  if (navigator.userAgent.search("iPhone") != -1 &&
      navigator.userAgent.search("Version/" != -1)) {
    element.focus()
    element.blur()
  }

  // This is mandatory for all browsers
  element.getElementsByTagName("iframe")[0].blur()
}

@michelle
Copy link
Collaborator

michelle commented Mar 9, 2018

Hi @Sylv3r!

Thanks for the note, and sorry for the trouble this has been causing you. We're actively working on a fix internally and will post an update when it's out.

@michelle
Copy link
Collaborator

This should now be fixed! Let us know if you're still seeing issues.

@afholderman
Copy link

We're still seeing this issue. On version 1.6.0 the keyboard persists after the submit action and the app has moved to the next page.

@cweiss-stripe
Copy link
Contributor

cweiss-stripe commented May 1, 2018

Hi @afholderman
I can not reproduce the issue anymore. Could you provide some info on your integration (a code snippet or a link) and the device (iOS / Safari version) you are still seeing the issue with?
Is it still broken for you on https://stripe.github.io/elements-examples/ ?

@afholderman
Copy link

@cweiss-stripe I was able to create a minimal repo and reproduce the issue on an ipad IOS 10.3.3. Once you click pay the keyboard will persist https://codesandbox.io/s/l72l6k779q

@cweiss-stripe
Copy link
Contributor

cweiss-stripe commented May 1, 2018

Thank you @afholderman I can confirm that I am also seeing this issue with react-stripe-elements and split card* fields on Mobile Safari.
(Heads up, that your codesandbox example is transitioning away before the token gets created, but after fixing this the keyboard behavior is still the same)

I'll reopen this PR and we'll post an update here once this is fixed.

@cweiss-stripe cweiss-stripe reopened this May 1, 2018
@cweiss-stripe cweiss-stripe self-assigned this May 14, 2018
@cweiss-stripe
Copy link
Contributor

@afholderman thanks again for providing the details!
This issue should be fixed now, you can check it e.g. here: https://codesandbox.io/s/5x09mrv58n
Let me know if it works for you!

@afholderman
Copy link

@cweiss-stripe we have confirmed the fix in codesandbox and our application, thank you!

@granmoe
Copy link

granmoe commented May 15, 2018

I found this issue through a google search. I'm having a similar issue in our private codebase in an input that has some formatting logic. It turned out that our issue was happening because we update the cursor position of the input (using a ref) in componentDidUpdate, which for some reason causes a random focus event to fire only in iOS. My fix was to just track whether or not the input has focus (and this doesn't and probably shouldn't be part of component state since it doesn't change what gets rendered, just make it a class property or a plain variable in the component's module scope), and only run the cursor updating logic within the componentDidUpdate if hasFocus === true and the position needs to be updated.

Just thought I'd throw this in here in case it helps with your issue.

@LeBenLeBen
Copy link

Can somebody please provide more information about how this has been fixed? I have the same issue with vue-stripe-elements and I’m not able to work around it using the information provided above.

@davebalmer
Copy link

Still an issue here, too. The keypad doesn't dismiss but worse is that even if the user dismisses it manually with "Done", it comes back later as they tap around. We're using elements directly -- no react or vue, etc.

@jackhair
Copy link

Same issue using ember-stripe-elements too.

@cweiss-stripe
Copy link
Contributor

@granmoe
Thanks for sharing your insights!

@LeBenLeBen @jackhair
We fixed the issue in the underlying stripe-js, so it should be fixed for all wrapper libraries as well. Do you have an example page where I still can reproduce the issue?

@davebalmer
Thanks for reporting this again. I can't reproduce it anymore on e.g. http://stripe.github.io/elements-examples/
Do you have a link to an example or a minimal reproduction where the problem still happens?

@jackhair
Copy link

@cweiss-stripe Thank you, can confirm this is fixed for us using the ember wrapper.

Which repo reflects the update for reference?

@LeBenLeBen
Copy link

LeBenLeBen commented May 30, 2018

@cweiss-stripe I can still reproduce the problem, but I think I narrowed the cause now. When I submit the form to get the token and then process the payment, I hide the Stripe Element and show a loader instead. In that specific case the bug happens. Here is a minimal reproduction case: https://codesandbox.io/s/0p8q30n30n (see App.vue file where every happens, except the Stripe JS file being included in index.html)

  1. Open the link above on an iOS device
  2. Fill-in the form with a test credit card (4242 4242 4242 4242)
  3. Submit
    => The keyboard stays open
  4. Close the keyboard manually with "Ok"
  5. Tap anywhere in the page, the keyboard opens

Could you please see if you can fix that case on your side as well or share any hints you would have to work around it? 🙇

@cweiss-stripe
Copy link
Contributor

cweiss-stripe commented May 30, 2018

@LeBenLeBen Thanks for the example!
After submit, on Mobile Safari, the Stripe Card Element tries to close the keyboard by focusing and blurring a hidden input, which happens asynchronously and takes some time.
In your case, you are removing the Element from the DOM on submit (with the if-directive that only renders the Element when loading === false), so the Element can't perform the steps to close the keyboard.
There are a few ways to mitigate this by not removing the Element from the DOM. You could hide it via css or place an item on top of it. Please let me know if that works for you!

@cweiss-stripe
Copy link
Contributor

@jackhair The change was made to the underlying Stripe.js library, which is not open source.

@LeBenLeBen
Copy link

@cweiss-stripe Actually I use v-show instead of v-if to hide the component from the page instead of removing it.

I tried to change the display: none (added by the v-show) to visibility: hidden but the result is the same. However if I use opacity: 0 the focus/blur happen and the keyboard is successfully hidden 🎉

I think I have enough information to work around it now, thanks for your help!

@alexander-v-ysbm
Copy link

alexander-v-ysbm commented Jun 12, 2018

Hi to All, I thing you get the separate problem to my, at iOS, maybe somebody can help me with stripe elements, I have use vue-stripe-elemetns and stripe-client packages but still get this on iPhone Safari.
When I focus one of element it become to send requests to get some gif from stripe server, but real phone just freezing down.
https://drive.google.com/file/d/13zxxwjFw4LKbEGumPRrbgczpMY59L8j2/view?usp=sharing

@cweiss-stripe

@binomialstew
Copy link

@alexander-v-ysbm, I'm seeing the same issue but using the current version of stripe.js directly with no wrapper. Using element.focus() is causing an infinite loop of alternating blur/focus GET requests to some gif on q.stripe.com, like you said. This effectively locks the site. I don't really understand why this is trying to get a gif, but it is sending elements.event.focus and elements.event.blur repeatedly as the event parameter for these requests.

@asolove-stripe
Copy link
Contributor

@binomialstew Yikes, that doesn't sound good! I'm looking at our logs and can't seem to find an instance of this happening. I also tried several things in our test pages and couldn't make this happen. Do you have a url or a set of steps that can reliably reproduce it?

@binomialstew
Copy link

@asolove-stripe, thanks for reaching out.

I just looked at this again and realize it was my fault. I'm using a setOutcome() function both on element change and form submit that uses the element.focus() method, like this example. When I remove the function on change, there is no infinite loop. It seems there is a change event in iOS on submit that is not triggered in desktop browsers.

@mmm111mmm
Copy link

Are you all using Firefox on iOS by any chance?

I just had this issue: I would click on an input box, then click 'x' or 'done' on the keyboard, and then whenever I clicked anywhere else the keyboard would pop back up.

The code that simulated it is here

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  </head>
  <body>
    <div>
      <input value="hiya">
    </div>
    <div>Sup with you???</div>
  </body>

</html>

It does not happen on Safari or Chrome.

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

No branches or pull requests