|
@@ -37,16 +37,15 @@ const positionConfigurations = {
|
37
|
37
|
|
38
|
38
|
$('.jitsipopover').css({
|
39
|
39
|
display: 'table',
|
40
|
|
- left: position.left,
|
41
|
|
- top: position.top
|
|
40
|
+ left: element.left,
|
|
41
|
+ top: element.top
|
42
|
42
|
});
|
43
|
43
|
|
44
|
44
|
// Move additional padding to the right edge of the popover and
|
45
|
45
|
// allow css to take care of width. The padding is used to maintain
|
46
|
46
|
// a hover state between the target and the popover.
|
47
|
|
- $('.jitsipopover > .jitsipopover__menu-padding').css({
|
48
|
|
- left: element.width
|
49
|
|
- });
|
|
47
|
+ $('.jitsipopover > .jitsipopover__menu-padding')
|
|
48
|
+ .css({ left: element.width });
|
50
|
49
|
|
51
|
50
|
// Find the distance from the top of the popover to the center of
|
52
|
51
|
// the target and use that value to position the arrow to point to
|
|
@@ -67,13 +66,21 @@ const positionConfigurations = {
|
67
|
66
|
at: "top",
|
68
|
67
|
collision: "fit",
|
69
|
68
|
using: function setPositionTop(position, elements) {
|
70
|
|
- var calcLeft = elements.target.left - elements.element.left +
|
71
|
|
- elements.target.width/2;
|
72
|
|
- $(".jitsipopover").css(
|
73
|
|
- {top: position.top, left: position.left, display: "table"});
|
74
|
|
- $(".jitsipopover > .arrow").css({left: calcLeft});
|
75
|
|
- $(".jitsipopover > .jitsipopover__menu-padding").css(
|
76
|
|
- {left: calcLeft - 50});
|
|
69
|
+ const { element, target } = elements;
|
|
70
|
+ const calcLeft = target.left - element.left + target.width / 2;
|
|
71
|
+ const paddingLeftPosition = calcLeft - 50;
|
|
72
|
+ const $jistiPopover = $('.jitsipopover');
|
|
73
|
+
|
|
74
|
+ $jistiPopover.css({
|
|
75
|
+ display: 'table',
|
|
76
|
+ left: element.left,
|
|
77
|
+ top: element.top
|
|
78
|
+ });
|
|
79
|
+ $jistiPopover.find('.arrow').css({ left: calcLeft });
|
|
80
|
+ $jistiPopover.find('.jitsipopover__menu-padding')
|
|
81
|
+ .css({ left: paddingLeftPosition });
|
|
82
|
+ $jistiPopover.find('.jitsipopover__menu-padding-top')
|
|
83
|
+ .css({ left: paddingLeftPosition });
|
77
|
84
|
}
|
78
|
85
|
}
|
79
|
86
|
};
|
|
@@ -93,8 +100,6 @@ export default (function () {
|
93
|
100
|
* Constructs new JitsiPopover and attaches it to the element
|
94
|
101
|
* @param element jquery selector
|
95
|
102
|
* @param options the options for the popover.
|
96
|
|
- * - {Function} onBeforePosition - function executed just before
|
97
|
|
- * positioning the popover. Useful for translation.
|
98
|
103
|
* @constructor
|
99
|
104
|
*/
|
100
|
105
|
function JitsiPopover(element, options)
|
|
@@ -132,6 +137,7 @@ export default (function () {
|
132
|
137
|
|
133
|
138
|
return (
|
134
|
139
|
`<div class="jitsipopover ${skin} ${position}">
|
|
140
|
+ <div class="jitsipopover__menu-padding-top"></div>
|
135
|
141
|
${arrow}
|
136
|
142
|
<div class="jitsipopover__content"></div>
|
137
|
143
|
<div class="jitsipopover__menu-padding"></div>
|
|
@@ -176,65 +182,41 @@ export default (function () {
|
176
|
182
|
* Creates the popover html.
|
177
|
183
|
*/
|
178
|
184
|
JitsiPopover.prototype.createPopover = function () {
|
179
|
|
- $("body").append(this.template);
|
180
|
|
- let popoverElem = $(".jitsipopover > .jitsipopover__content");
|
181
|
|
-
|
182
|
|
- const { content } = this.options;
|
183
|
|
-
|
184
|
|
- if (React.isValidElement(content)) {
|
185
|
|
- /* jshint ignore:start */
|
186
|
|
- ReactDOM.render(
|
187
|
|
- <I18nextProvider i18n = { i18next }>
|
188
|
|
- { content }
|
189
|
|
- </I18nextProvider>,
|
190
|
|
- popoverElem.get(0),
|
191
|
|
- () => {
|
192
|
|
- // FIXME There seems to be odd timing interaction when a
|
193
|
|
- // React Component is manually removed from the DOM and then
|
194
|
|
- // created again, as the ReactDOM callback will fire before
|
195
|
|
- // render is called on the React Component. Using a timeout
|
196
|
|
- // looks to bypass this behavior, maybe by creating
|
197
|
|
- // different execution context. JitsiPopover should be
|
198
|
|
- // rewritten into react soon anyway or at least rewritten
|
199
|
|
- // so the html isn't completely torn down with each update.
|
200
|
|
- setTimeout(() => this._popoverCreated());
|
201
|
|
- });
|
202
|
|
- /* jshint ignore:end */
|
203
|
|
- return;
|
204
|
|
- }
|
|
185
|
+ let $popover = $('.jitsipopover');
|
205
|
186
|
|
206
|
|
- popoverElem.html(content);
|
207
|
|
- this._popoverCreated();
|
208
|
|
- };
|
|
187
|
+ if (!$popover.length) {
|
|
188
|
+ $('body').append(this.template);
|
209
|
189
|
|
210
|
|
- /**
|
211
|
|
- * Adds listeners and executes callbacks after the popover has been created
|
212
|
|
- * and displayed.
|
213
|
|
- *
|
214
|
|
- * @private
|
215
|
|
- * @returns {void}
|
216
|
|
- */
|
217
|
|
- JitsiPopover.prototype._popoverCreated = function () {
|
218
|
|
- const { onBeforePosition } = this.options;
|
|
190
|
+ $popover = $('.jitsipopover');
|
219
|
191
|
|
220
|
|
- if (typeof onBeforePosition === 'function') {
|
221
|
|
- onBeforePosition($(".jitsipopover"));
|
|
192
|
+ $popover.on('mouseenter', () => {
|
|
193
|
+ this.popoverIsHovered = true;
|
|
194
|
+ if (typeof this.onHoverPopover === 'function') {
|
|
195
|
+ this.onHoverPopover(this.popoverIsHovered);
|
|
196
|
+ }
|
|
197
|
+ });
|
|
198
|
+
|
|
199
|
+ $popover.on('mouseleave', () => {
|
|
200
|
+ this.popoverIsHovered = false;
|
|
201
|
+ this.hide();
|
|
202
|
+ if (typeof this.onHoverPopover === 'function') {
|
|
203
|
+ this.onHoverPopover(this.popoverIsHovered);
|
|
204
|
+ }
|
|
205
|
+ });
|
222
|
206
|
}
|
223
|
207
|
|
224
|
|
- $('.jitsipopover').on('mouseenter', () => {
|
225
|
|
- this.popoverIsHovered = true;
|
226
|
|
- if (typeof this.onHoverPopover === 'function') {
|
227
|
|
- this.onHoverPopover(this.popoverIsHovered);
|
228
|
|
- }
|
229
|
|
- }).on('mouseleave', () => {
|
230
|
|
- this.popoverIsHovered = false;
|
231
|
|
- this.hide();
|
232
|
|
- if (typeof this.onHoverPopover === 'function') {
|
233
|
|
- this.onHoverPopover(this.popoverIsHovered);
|
234
|
|
- }
|
235
|
|
- });
|
|
208
|
+ const $popoverContent = $popover.find('.jitsipopover__content');
|
236
|
209
|
|
237
|
|
- this.refreshPosition();
|
|
210
|
+ /* jshint ignore:start */
|
|
211
|
+ ReactDOM.render(
|
|
212
|
+ <I18nextProvider i18n = { i18next }>
|
|
213
|
+ { this.options.content }
|
|
214
|
+ </I18nextProvider>,
|
|
215
|
+ $popoverContent.get(0),
|
|
216
|
+ () => {
|
|
217
|
+ this.refreshPosition();
|
|
218
|
+ });
|
|
219
|
+ /* jshint ignore:end */
|
238
|
220
|
};
|
239
|
221
|
|
240
|
222
|
/**
|
|
@@ -264,9 +246,9 @@ export default (function () {
|
264
|
246
|
*/
|
265
|
247
|
JitsiPopover.prototype.updateContent = function (content) {
|
266
|
248
|
this.options.content = content;
|
267
|
|
- if(!this.popoverShown)
|
|
249
|
+ if (!this.popoverShown) {
|
268
|
250
|
return;
|
269
|
|
- this.remove();
|
|
251
|
+ }
|
270
|
252
|
this.createPopover();
|
271
|
253
|
};
|
272
|
254
|
|
|
@@ -279,11 +261,9 @@ export default (function () {
|
279
|
261
|
JitsiPopover.prototype.remove = function () {
|
280
|
262
|
const $popover = $('.jitsipopover');
|
281
|
263
|
const $popoverContent = $popover.find('.jitsipopover__content');
|
282
|
|
- const attachedComponent = $popoverContent.get(0);
|
283
|
264
|
|
284
|
|
- if (attachedComponent) {
|
285
|
|
- // ReactDOM will no-op if no React Component is found.
|
286
|
|
- ReactDOM.unmountComponentAtNode(attachedComponent);
|
|
265
|
+ if ($popoverContent.length) {
|
|
266
|
+ ReactDOM.unmountComponentAtNode($popoverContent.get(0));
|
287
|
267
|
}
|
288
|
268
|
|
289
|
269
|
$popover.off();
|