I experience a weird ios keyboard issue on our pwa web page.
As the photo below, the keyboard body disppear while the toolbar remains. And once this situation appear, it will keep like that until I restart the pwa app.
We use react and the input element is a Material-ui Textfield. While there have some conditional render on parent component
function handleChange(e) {
var value = e.target.value;
setValue(value);
return 0
};
<MaterialUi_TextField
inputProps={"title": "quantity", "onFocus": onFocus, "onBlur": onBlur}
type={"number"}
value={value}
onChange={handleChange}
/>;
other info to mention:
ios version = 13.4.1, 13.6
there is a meta user-scalable=0 on the page
Related
I have an app that I've built in React Native where I have a modal that will appear when a button is pressed and prompts the user for input. I've made other modals in the app that work fine using the same method that I am using now. But when I change the state for this modal that determines whether the modal is visible, it seems to completely ignore it and does not display. The modal works on my android and on my many android emulators but it does not work on my iphone 10 for some reason.
I have a file GameScreen.js that is the screen component and holds the modal within it. It also holds the relevant methods and state for the modal's visibility:
import {
Body,
Button,
Container,
Content,
Header,
Icon,
Left,
Right,
View } from 'native-base';
import { BackHandler, StyleSheet, Text, TextInput, TouchableOpacity, Platform } from 'react-native';
import React, { Component, createRef } from 'react';
import myModal from '../components/myModal';
export default class GameScreen extends Component {
constructor(props) {
super(props)
this.state = {
// other state
isVisible: false,
}
this.displayModal = this.displayModal.bind(this);
}
displayModal(show) {
this.setState({
isVisible: show
})
}
render() {
return (
<Container>
<myModal
displayModal={this.displayModal}
isVisible={this.state.isVisible}
/>
<View>
<TouchableOpacity
style={styles.button}
onPress{() => this.displayModal(true)} >
<Image />
</TouchableOpacity>
</View>
</Container>
)
}
}
I have the modal in its own file and it looks like this (myModal.js):
import {
Button,
Card,
CardItem,
Container,
Text,
View } from 'native-base';
import { Modal, StyleSheet } from 'react-native';
import React, { Component } from 'react';
export default class myModal extends Component {
render() {
return (
<Container>
<Modal
transparent
animationType='fade'
visible={this.props.isVisible}
onRequestClose={() => this.props.displayModal(false)}
>
<View>
// My view stuff
</View>
</Modal>
</Container>
)
}
}
I have tried putting console logs in the modal file to see if the state is actually changing and it does seem to be. I've added a log of the isVisible state in render() and in a componentDidUpdate() and it always logs out true once I have pressed the button in GameScreen but it seems like the modal is ignoring it. When I manually change the 'visible' prop to true it displays fine so it's not as if it has a problem with what I want to render.
I've also tried to run expo in production mode as some people have cited issues with dev mode and react native modals. I started the metro bundler with 'expo start --no-dev --minify' as the expo docs suggest but the problem persists.
As I said above, this exact approach is working fine in other parts of the app but seems to not like the GameScreen for some reason. And, this problem ONLY happens on iOS. I don't have any other iphones and don't have an access to a mac for xCode so I guess it might be the phone itself but it renders the other modals I have on my app just fine. I've been banging my head on the keyboard trying to get this weird bug figured out for a while, so thank you for any responses!!
So I just now figured it out and it was a dumb solution that I hope will help someone else. Thank you #Kamal Hossain, your suggestion helped me diagnose the problem.
So in my GameScreen, I was using an API called react-native-actions-sheet which is this nice little drawer UI component which held the button that was trying to open the modal. The button also closed the drawer after it was pressed. The button was interacting with the state just fine, but I think the process of closing the drawer was messing with the modal rendering somehow.
My working solution is to make the button wait for a fraction of a second before attempting to open the modal on ios and it works just fine now:
<TouchableOpacity
onPress={() => {
// closes drawer
this.props.toggleActionSheetVisibility();
// waits if on ios and then opens modal
setTimeout(() => this.displayModal(true), Platform.OS === "ios" ? 200 : 0);
}}
/>
I don't know why it was only happening on ios specifically but I hope this helps someone in the future.
Here is a test web page:
https://codepen.io/zephyr103/pen/KOxgzL
includes code like:
body.no-scroll {
overflow: hidden;
}
It works in my MacOSX browsers (including the iOS/Android simulators in Chrome) and usually works fine in Android. It has problems in Safari, Chrome and Firefox in iOS.
When you click "Short Quote" or "Long Quote" it has a variable height fixed position popup with a transparent grey overlay that you can click on to exit the popup.
When you scroll (using touch dragging or mouse wheel) the popup or overlay it is meant to either ignore it (when you scroll the grey overlay) or scroll the popup content - if some is hidden. If none of the popup is hidden then it also ignores drags.
This is how it works:
The #text-viewer popup uses overflow-y auto. When the popup is active it adds the "no-scroll" class to the body element. This class has the css of "hidden" for overflow. This is supposed to stop the body from scrolling whether you are dragging the popup or the grayed out overlay.
On iOS the transparent overlay can be scrolled and when you scroll the "Short Quote" popup it also scrolls the body. When dragging the short quote popup nothing is supposed to scroll.
I guess what you ought to do for Safari is to add
body.no-scroll {
overflow: hidden;
-webkit-overflow-scrolling: touch;
}
Also, when you open popup add to the body this code as well in JavaScript
body.ontouchstart = (e) => {
e.preventDefault();
};
If you want to remove scrollbar then you need to calculate its width
const documentWidth = document.documentElement.clientWidth;
const windowWidth = window.innerWidth;
const scrollBarWidth = windowWidth - documentWidth;
and then add padding right to body with the ${scrollBarWidth}px
I found a solution for iOS Safari, Chrome and Firefox
https://codepen.io/zephyr103/pen/mNzoGE
I removed the no-scroll class and styling for the body element.
When the popup is being shown:
var targetElement = document.querySelector("#text-viewer");
bodyScrollLock.disableBodyScroll(targetElement);
When the popup is being hidden:
bodyScrollLock.clearAllBodyScrollLocks();
The js file:
https://github.com/willmcpo/body-scroll-lock/tree/master/lib
Usage:
https://www.npmjs.com/package/body-scroll-lock
The only problem is that the long quote popup doesn't shrink to fit on the screen in iOS Safari and Chrome (sometimes is ok in iOS Firefox)
After close the dialog, do this for iphone
$('html').removeAttr('style');
$('body').removeAttr('style');
When I go full screen on an element and then try to display angular bootstrap's modal in front, it won't appear in front.
To test it:
1 - Click on this link http://plnkr.co/edit/oKZHZZebyNMwpG114Jyy?p=preview
2 - Click on the "launch the preview in separate window" icon (image shown below)
3 - Click on Go Full Screen Button (you will then be in full screen on the element with id fullable)
4 - Then click on any of the buttons to try to show a modal.
Here is how to "launch the preview in separate window" on plnkr:
Solution to this problem required modal window to be appended to the element of my choice (in this case, element that goes full screen).
To accomplish this, I updated the angular bootstrap modal's code so that options object we pass to the $modal.open() function now accepts an appendTo property which is a css selector that will be used by document.querySelector.
In modal code (version 0.12.1), I changed from these:
var body = $document.find('body').eq(0),
currBackdropIndex = backdropIndex();
...
$modalStack.open(modalInstance, {
scope: modalScope,
deferred: modalResultDeferred,
content: tplAndVars[0],
backdrop: modalOptions.backdrop,
keyboard: modalOptions.keyboard,
backdropClass: modalOptions.backdropClass,
windowClass: modalOptions.windowClass,
windowTemplateUrl: modalOptions.windowTemplateUrl,
size: modalOptions.size
});
to these:
var body = angular.element(document.querySelector(modal.appendTo)),
currBackdropIndex = backdropIndex();
...
$modalStack.open(modalInstance, {
scope: modalScope,
deferred: modalResultDeferred,
content: tplAndVars[0],
backdrop: modalOptions.backdrop,
keyboard: modalOptions.keyboard,
backdropClass: modalOptions.backdropClass,
windowClass: modalOptions.windowClass,
windowTemplateUrl: modalOptions.windowTemplateUrl,
size: modalOptions.size,
appendTo: modalOptions.appendTo || 'body'
});
I opened an issue for this on github but it was closed without resolution so I had to update my local copy. Github issue is here: https://github.com/angular-ui/bootstrap/issues/3686
Please note: Since I am using document.querySelector for this, fix will work on browsers that support document.querySelector (almost all plus IE >= 9) http://caniuse.com/#feat=queryselector
I have an html input text element in my application with jQuery blur event handler:
$('#textBox').blur(function () { console.log('blur'); })
When I click on a page area out of the textbox, desktop browsers fire this event, but iPad Safari does not. And neither the keyboard nor the cursor does not disappear. Are there any ways to "enable" the blur event ?
By design, a tap away will remove the hover state but the textbox will remain focused.
Safari Web Content Guide should help you develop for Safari on IOS devices.
Workaround (albeit not recommended): https://codepen.io/kevinfarrugia/pen/rKpRBL
document.getElementById("container").addEventListener("click", () => {
document.getElementById("container").focus();
});
In iPad Safari browser, when I change focus from a textbox to a dropdown, the keyboard still remains... Is there some way (maybe with Javascript) I can hide the keyboard when user blurs from the textbox?
Indirectly speaking, I am looking for a equivalent of (but in Mobile Safari)
[tempTextField resignFirstResponder];
I found the solution for this at http://uihacker.blogspot.com/2011/10/javascript-hide-ios-soft-keyboard.html. Essentially, just do this (it worked for me):
var hideKeyboard = function() {
document.activeElement.blur();
$("input").blur();
};
I had iPad with iOS 5.0.1 not hiding the keyboard after successful login on my site. I solved by simply executing the javascript command
document.activeElement.blur();
after successful login and now the keyboard is correctly hidden :-)
I know this is a slightly older question, but I discovered the answer today for this, and the answer is embarrassingly simple... I spent way more time than I would like to admit figuring this out ;)
To prevent showing the keyboard on:
<input type="text" name="someInput" />
for when you want to do something like use a jQuery UI datepicker...
add a readonly attribute like so:
<input type="text" name="someInput" readonly="readonly" />
If you are trying to be mindful of people with JS turned off, you could always leave off the attribute and add it in your code:
$('[name=someInput]').attr('readonly','readonly');
Hope this helps.
Here is a jsFiddle demonstrating the concept: http://jsfiddle.net/3QLBz/5/
$("#txt").on("focus", function(){
$(this).blur();
});
works with jquery UI datepicker on IPad
Natively, iPad, iPhone keyboard should disappear when the input looses focus.
I figured out on mobile/tablet devices that
Safari only handles click event for elements having cursor:pointer
property.
I've finally added cursor:pointer on the body tag for mobile/tablet devices and it works like a charm.
Little sample
body {
#media (max-width: 1024px) { /* IPad breakpoint */
cursor: pointer; /* Fix iPhone/iPad click issue */
}
}
Version without jQuery:
function hideKeyboard () {
document.activeElement.blur();
Array.prototype.forEach.call(document.querySelectorAll('input, textarea'), function(it) {
it.blur();
});
}
I call .focus() on another textfield and the keyboard disappears. I'm using the Sencha touch framework, the textfield im referring to is an Ext.Text object.
I know this is counter-intuitive, but it seems to work for me
Sample.views.MessageBar.getComponent(0).blur();
document.activeElement.blur();
window.focus();
Sample.views.sendMessageBar.getComponent(0).setDisabled(true);
You can use codes above. First and Forth lines are for that textfield. It works on iphone but it doesnt work on Android. I tried Iphone 3gs and samsung galaxy s2.
According to Apple Safari documentation, when you select a dropdown (select list) the iOS dismisses the keyboard and displays native iOS select control. Make sure you use SELECT element for your dropdown list
and also try adding this to your meta tags for the page
<meta name="apple-mobile-web-app-capable" content="yes" />