在iOS safari中,当触发外部时,触发=“焦点”的OverlayTrigger无法解除。这是我的代码:
<OverlayTrigger
trigger="focus"
placement="right"
overlay={ <Popover id="popoverID" title="Popover Title">
What a popover...
</Popover> } >
<a bsStyle="default" className="btn btn-default btn-circle" role="Button" tabIndex={18}>
<div className="btn-circle-text">?</div>
</a>
</OverlayTrigger>
我知道这是Bootstrap cuz的一个已知错误,这甚至不适用于iOS中的their own website,但有没有人知道任何解决方法?如果它不需要jQuery,那将是最好的,但jQuery解决方案是受欢迎的。感谢。
答案 0 :(得分:1)
好的,既然没有其他人给我解决方法,我和同事一起解决了这个问题3天,我们想出了这个重要的解决方案:
问题:
使用触发器=&#34;焦点&#34;,在弹出窗口/工具提示外单击但不触及时,可以取消Bootstrap Popover / Tooltip。 Android浏览器显然会自动更改点击次数,因此在Android上运行良好。但是基于iOS Safari(iOS chrome,iOS firefox等)的iOS Safari和浏览器不能做到这一点。
THE FIX:
我们发现在React Bootstrap中,Overlay组件实际上允许您自定义何时显示Popover / Tooltip,因此我们基于Overlay构建了此组件InfoOverlay。要处理组件外部的点击,我们需要为Popover / Tooltip和窗口添加事件监听器,以处理“mousedown”和“mousedown”。并且&#39; touchstart&#39;。此外,此方法将使Popover始终具有其最小宽度,因为组件的填充权最初为0px,并且我们基于某个父组件的宽度进行制作,以便它基于父组件响应。代码如下所示:
import React, { Component, PropTypes as PT } from 'react';
import {Popover, Overlay} from 'react-bootstrap';
export default class InfoOverlay extends Component {
static propTypes = {
PopoverId: PT.string,
PopoverTitle: PT.string,
PopoverContent: PT.node,
// You need to add this prop and pass it some numbers
// if you need to customize the arrowOffsetTop, it's sketchy...
arrowOffsetTop: PT.number,
// This is to be able to select the parent component
componentId: PT.string
}
constructor(props) {
super(props);
this.state = {
showPopover: false,
popoverClicked: false
};
}
componentDidMount() {
// Here are the event listeners and an algorithm
// so that clicking popover would not dismiss itself
const popover = document.getElementById('popoverTrigger');
if (popover) {
popover.addEventListener('mousedown', () => {
this.setState({
popoverClicked: true
});
});
popover.addEventListener('touchstart', () => {
this.setState({
popoverClicked: true
});
});
}
window.addEventListener('mousedown', () => {
if (!this.state.popoverClicked) {
this.setState({
showPopover: false
});
} else {
this.setState({
popoverClicked: false
});
}
});
window.addEventListener('touchstart', () => {
if (!this.state.popoverClicked) {
this.setState({
showPopover: false
});
} else {
this.setState({
popoverClicked: false
});
}
});
// this is to resize padding-right when window resizes
window.onresize = ()=>{
this.setState({});
};
}
// This function sets the style and more importantly, padding-right
getStyle() {
if (document.getElementById(this.props.componentId) && document.getElementById('popoverTrigger')) {
const offsetRight = document.getElementById(this.props.componentId).offsetWidth - document.getElementById('popoverTrigger').offsetLeft - 15;
return (
{display: 'inline-block', position: 'absolute', 'paddingRight': offsetRight + 'px'}
);
}
return (
{display: 'inline-block', position: 'absolute'}
);
}
overlayOnClick() {
this.setState({
showPopover: !(this.state.showPopover)
});
}
render() {
const customPopover = (props) => {
return (
{/* The reason why Popover is wrapped by another
invisible Popover is so that we can customize
the arrowOffsetTop, it's sketchy... */}
<div id="customPopover">
<Popover style={{'visibility': 'hidden', 'width': '100%'}}>
<Popover {...props} arrowOffsetTop={props.arrowOffsetTop + 30} id={this.props.PopoverId} title={this.props.PopoverTitle} style={{'marginLeft': '25px', 'marginTop': '-25px', 'visibility': 'visible'}}>
{this.props.PopoverContent}
</Popover>
</Popover>
</div>
);
};
return (
<div id="popoverTrigger" style={this.getStyle()}>
<a bsStyle="default" className="btn btn-default btn-circle" onClick={this.overlayOnClick.bind(this)} role="Button" tabIndex={13}>
<div id="info-button" className="btn-circle-text">?</div>
</a>
<Overlay
show={this.state.showPopover}
placement="right"
onHide={()=>{this.setState({showPopover: false});}}
container={this}>
{customPopover(this.props)}
</Overlay>
</div>
);
}
}
最后,这是一个繁重的工作,因为它是一个大量的修复代码,你可能会觉得你的网站由于4个事件监听器而减慢了一点点。最好的解决方案是告诉Bootstrap解决这个问题......