|
155 | 155 | /**
|
156 | 156 | * Class property to be used for Popover rendering
|
157 | 157 | *
|
158 |
| - * @return string |
| 158 | + * @return String |
159 | 159 | */
|
160 | 160 | popoverAlignment() {
|
161 | 161 | return !this.placement || this.placement === `default` ? `popover-top` : `popover-${this.placement}`;
|
|
164 | 164 | /**
|
165 | 165 | * Determine if the Popover should be shown.
|
166 | 166 | *
|
167 |
| - * @return boolean |
| 167 | + * @return Boolean |
168 | 168 | */
|
169 | 169 | showState() {
|
170 | 170 | return this.show !== false && (this.triggerState || this.show);
|
171 |
| - }, |
172 |
| -
|
173 |
| - /** |
174 |
| - * Tether construct params for each show event. |
175 |
| - * |
176 |
| - * @return Object |
177 |
| - */ |
178 |
| - tetherOptions() { |
179 |
| - return { |
180 |
| - element: this._popover, |
181 |
| - target: this._trigger, |
182 |
| - offset: this.offset, |
183 |
| - constraints: this.constraints, |
184 |
| - attachment: placementParams[this.placement].attachment, |
185 |
| - targetAttachment: placementParams[this.placement].targetAttachment |
186 |
| - }; |
187 |
| - }, |
188 |
| -
|
189 |
| - /** |
190 |
| - * Determine if debounce should be used. |
191 |
| - * |
192 |
| - * @return boolean |
193 |
| - */ |
194 |
| - useDebounce() { |
195 |
| - return this.normalizedTriggers.length > 1; |
196 | 171 | }
|
197 | 172 | },
|
198 | 173 |
|
199 | 174 | watch: {
|
| 175 | + /** |
| 176 | + * Refresh Tether display properties |
| 177 | + */ |
200 | 178 | constraints() {
|
201 | 179 | this.setOptions();
|
202 | 180 | },
|
203 | 181 |
|
204 |
| - content() { |
205 |
| - this.refreshPosition(); |
206 |
| - }, |
207 |
| -
|
| 182 | + /** |
| 183 | + * Refresh Popover event triggers |
| 184 | + * @param {Array} newTriggers |
| 185 | + * @param {Array} oldTriggers |
| 186 | + */ |
208 | 187 | normalizedTriggers(newTriggers, oldTriggers) {
|
209 | 188 | this.updateListeners(newTriggers, oldTriggers);
|
210 | 189 | },
|
211 | 190 |
|
| 191 | + /** |
| 192 | + * Refresh Tether display properties |
| 193 | + */ |
212 | 194 | offset() {
|
213 | 195 | this.setOptions();
|
214 | 196 | },
|
215 | 197 |
|
| 198 | + /** |
| 199 | + * Refresh Tether display properties |
| 200 | + */ |
216 | 201 | placement() {
|
217 | 202 | this.setOptions();
|
218 | 203 | },
|
219 | 204 |
|
220 | 205 | /**
|
221 | 206 | * Affect 'show' state in response to status change
|
222 |
| - * @param {Boolean} newShowState |
| 207 | + * @param {Boolean} val |
223 | 208 | */
|
224 | 209 | showState(val) {
|
225 | 210 | clearTimeout(this._timeout);
|
226 | 211 | let delay = this.getDelay(val);
|
227 | 212 |
|
228 | 213 | if (delay)
|
229 |
| - this._timeout = setTimeout(() => {this.togglePopover(val)}, delay); |
| 214 | + this._timeout = setTimeout(() => this.togglePopover(val), delay); |
230 | 215 | else
|
231 | 216 | this.togglePopover(val);
|
232 |
| - }, |
233 |
| -
|
234 |
| - title() { |
235 |
| - this.refreshPosition(); |
236 | 217 | }
|
237 | 218 | },
|
238 | 219 |
|
|
249 | 230 | },
|
250 | 231 |
|
251 | 232 | /**
|
252 |
| - * Cleanup component listeners |
| 233 | + * Tidy removal of Tether object from the DOM |
253 | 234 | */
|
254 |
| - cleanup() { |
255 |
| - // Remove all event listeners |
256 |
| - // eslint-disable-next-line guard-for-in |
257 |
| - for (const trigger in this.normalizedTriggers) { |
258 |
| - this.removeListener(trigger); |
259 |
| - } |
260 |
| -
|
261 |
| - clearTimeout(this._timeout); |
262 |
| - this._timeout = null; |
263 |
| - this.hidePopover(); |
264 |
| - }, |
265 |
| -
|
266 | 235 | destroyTether() {
|
267 | 236 | if (this._tether) {
|
268 | 237 | this._tether.destroy();
|
|
275 | 244 | * @param {Object} e
|
276 | 245 | */
|
277 | 246 | eventHandler(e) {
|
278 |
| - // If this event is right after a previous successful event, ignore it |
279 |
| - if (this.useDebounce && this.debounce > 0 && this.lastEvent !== null && e.timeStamp <= this.lastEvent + this.debounce) { |
| 247 | + // If this event is right after a previous successful event, ignore it (debounce) |
| 248 | + if (this.normalizedTriggers.length > 1 && this.debounce > 0 && this.lastEvent !== null && e.timeStamp <= this.lastEvent + this.debounce) { |
280 | 249 | return;
|
281 | 250 | }
|
282 | 251 |
|
|
311 | 280 | return this.delay;
|
312 | 281 | },
|
313 | 282 |
|
| 283 | + /** |
| 284 | + * Tether construct params for each show event. |
| 285 | + * |
| 286 | + * @return Object |
| 287 | + */ |
| 288 | + getTetherOptions() { |
| 289 | + return { |
| 290 | + element: this._popover, |
| 291 | + target: this._trigger, |
| 292 | + offset: this.offset, |
| 293 | + constraints: this.constraints, |
| 294 | + attachment: placementParams[this.placement].attachment, |
| 295 | + targetAttachment: placementParams[this.placement].targetAttachment |
| 296 | + }; |
| 297 | + }, |
| 298 | +
|
314 | 299 | /**
|
315 | 300 | * Hide popover and fire event
|
316 | 301 | */
|
317 | 302 | hidePopover() {
|
318 | 303 | this._popover.style.display = 'none';
|
319 |
| - this.$root.$emit('hidden::popover'); |
320 |
| -
|
321 | 304 | this.destroyTether();
|
322 | 305 | },
|
323 | 306 |
|
|
326 | 309 | */
|
327 | 310 | refreshPosition() {
|
328 | 311 | if (this._tether) {
|
329 |
| - this.$nextTick(() => { this._tether.position(); }); |
| 312 | + this.$nextTick(() => {this._tether.position()}); |
330 | 313 | }
|
331 | 314 | },
|
332 | 315 |
|
|
346 | 329 | */
|
347 | 330 | setOptions() {
|
348 | 331 | if (this._tether) {
|
349 |
| - this._tether.setOptions(this.tetherOptions); |
| 332 | + this._tether.setOptions(this.getTetherOptions()); |
350 | 333 | }
|
351 | 334 | },
|
352 | 335 |
|
|
359 | 342 |
|
360 | 343 | // Let tether do the magic, after element is shown
|
361 | 344 | this._popover.style.display = 'block';
|
362 |
| - this._tether = new Tether(this.tetherOptions); |
| 345 | + this._tether = new Tether(this.getTetherOptions()); |
363 | 346 |
|
364 | 347 | // Make sure the popup is rendered in the correct location
|
365 | 348 | this.refreshPosition();
|
366 |
| -
|
367 |
| - this.$root.$emit('shown::popover'); |
368 | 349 | },
|
369 | 350 |
|
| 351 | + /** |
| 352 | + * Handle Popover show or hide instruction |
| 353 | + */ |
370 | 354 | togglePopover(newShowState) {
|
371 | 355 | this.$emit('showChange', newShowState);
|
372 | 356 | if (newShowState) {
|
373 | 357 | this.showPopover();
|
| 358 | + this.$root.$emit('shown::popover'); |
374 | 359 | } else {
|
375 | 360 | this.hidePopover();
|
| 361 | + this.$root.$emit('hidden::popover'); |
376 | 362 | }
|
377 | 363 | },
|
378 | 364 |
|
|
406 | 392 | },
|
407 | 393 |
|
408 | 394 | created() {
|
409 |
| - const hub = this.$root; |
410 |
| - hub.$on('hide::popover', () => { |
| 395 | + this.$root.$on('hide::popover', () => { |
411 | 396 | this.triggerState = false;
|
412 | 397 | });
|
413 |
| -
|
414 |
| - // Workaround to resolve issues like #151 |
415 |
| - if (this.$router) { |
416 |
| - this.$router.beforeEach((to, from, next) => { |
417 |
| - next(); |
418 |
| - this.cleanup(); |
419 |
| - }); |
420 |
| - } |
421 |
| -
|
422 |
| - const cleanup = () => { |
423 |
| - this.cleanup(); |
424 |
| - }; |
425 |
| -
|
426 |
| - hub.$on('hide::modal', cleanup); |
427 |
| - hub.$on('changed::tab', cleanup); |
428 | 398 | },
|
429 | 399 |
|
430 | 400 | mounted() {
|
|
443 | 413 | }
|
444 | 414 | },
|
445 | 415 |
|
446 |
| - /* |
447 |
| - beforeUpdate() { |
448 |
| - console.log('called beforeUpdate'); |
449 |
| - }, |
450 |
| -
|
451 | 416 | updated() {
|
452 |
| - console.log('called update'); |
453 |
| - } |
454 |
| - */ |
| 417 | + this.refreshPosition(); |
| 418 | + }, |
455 | 419 |
|
456 | 420 | beforeDestroy() {
|
457 |
| - this.cleanup(); |
| 421 | + this.normalizedTriggers.forEach(item => this.removeListener(item)); |
| 422 | + clearTimeout(this._timeout); |
| 423 | + this.destroyTether(); |
458 | 424 | }
|
459 | 425 | };
|
460 | 426 |
|
|
0 commit comments