OK,因为没有其他人围绕给我的工作,我曾在这个问题上与我的同事一起为3天,我们来到了这个沉重的解决方案:
问题:
当trigger =“focus”时,当在Popover/Tooltip外部单击而不是触摸时,Bootstrap Popover/Tooltip可以被解除。 Android浏览器显然会自动更改点击次数,所以Android上的事情很好。但是基于iOS safari(iOS chrome,iOS firefox等)的iOS Safari和浏览器不这么做。
THE FIX:
我们发现,在阵营引导,覆盖组件实际上允许您自定义的时候,显示酥料饼/工具提示,所以我们建立了基于覆盖该组件InfoOverlay。为了处理组件外部的点击,我们需要为Popover/Tooltip和窗口添加事件监听器来处理'mousedown'和'touchstart'。另外,这种方法会使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来解决这个问题...