Newer
Older
Allen Gilliland
committed
'use strict';
/*global document, Tether*/
import PopoverContent from './popover_content.react'
export default React.createClass({
Allen Gilliland
committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
displayName: 'PopoverWithTrigger',
getInitialState: function() {
return {
modalOpen: false
};
},
componentWillMount: function() {
var popoverContainer = document.createElement('span');
popoverContainer.className = 'PopoverContainer';
this._popoverElement = popoverContainer;
// TODO: we probably should put this somewhere other than body because then
// its outside our ng-view and could cause lots of issues
document.querySelector('body').appendChild(this._popoverElement);
},
componentDidMount: function() {
this._renderPopover();
},
componentDidUpdate: function() {
this._renderPopover();
},
componentWillUnmount: function() {
this._tether.destroy();
React.unmountComponentAtNode(this._popoverElement);
if (this._popoverElement.parentNode) {
this._popoverElement.parentNode.removeChild(this._popoverElement);
}
this._tether = undefined;
},
toggleModal: function() {
var modalOpen = !this.state.modalOpen;
this.setState({
modalOpen: modalOpen
});
},
_popoverComponent: function() {
return (
<PopoverContent handleClickOutside={this.toggleModal}>
<div className={this.props.className}>
{this.props.children}
</div>
</PopoverContent>
);
},
_tetherOptions: function() {
// sensible defaults for most popovers
return {
attachment: 'bottom right',
targetAttachment: 'top right',
targetOffset: '10px 0',
optimizations: {
moveElement: false // always moves to <body> anyway!
}
};
},
_renderPopover: function() {
if (this.state.modalOpen) {
// modal is open, lets do this!
React.render(this._popoverComponent(), this._popoverElement);
var tetherOptions = (this.props.tetherOptions) ? this.props.tetherOptions : this._tetherOptions();
// NOTE: these must be set here because they relate to OUR component and can't be passed in
tetherOptions.element = this._popoverElement;
tetherOptions.target = this.getDOMNode();
if (this._tether !== undefined && this._tether !== null) {
this._tether.setOptions(tetherOptions);
} else {
this._tether = new Tether(tetherOptions);
}
} else {
// if the modal isn't open then actively unmount our popover
React.unmountComponentAtNode(this._popoverElement);
}
},
render: function() {
return (
<span>
<a className="mx1" href="#" onClick={this.toggleModal}>
{this.props.triggerElement}
</a>
</span>
);
}