Skip to content

Commit e578532

Browse files
committed
fix(Popover): with hover and click triggers closes on mouseleave
1 parent 41e7123 commit e578532

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

js/src/tooltip.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ class Tooltip extends BaseComponent {
451451
if (trigger === 'click') {
452452
EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => {
453453
const context = this._initializeOnDelegatedTarget(event)
454+
context._activeTrigger[TRIGGER_CLICK] = !(context._isShown() && context._activeTrigger[TRIGGER_CLICK])
454455
context.toggle()
455456
})
456457
} else if (trigger !== TRIGGER_MANUAL) {

js/tests/unit/popover.spec.js

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import EventHandler from '../../src/dom/event-handler.js'
22
import Popover from '../../src/popover.js'
3-
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
3+
import {
4+
clearFixture, getFixture, jQueryMock, createEvent
5+
} from '../helpers/fixture.js'
46

57
describe('Popover', () => {
68
let fixtureEl
@@ -58,7 +60,7 @@ describe('Popover', () => {
5860
describe('show', () => {
5961
it('should toggle a popover after show', () => {
6062
return new Promise(resolve => {
61-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://twitter.com/getbootstrap">BS twitter</a>'
63+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
6264

6365
const popoverEl = fixtureEl.querySelector('a')
6466
const popover = new Popover(popoverEl)
@@ -78,7 +80,7 @@ describe('Popover', () => {
7880

7981
it('should show a popover', () => {
8082
return new Promise(resolve => {
81-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
83+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
8284

8385
const popoverEl = fixtureEl.querySelector('a')
8486
const popover = new Popover(popoverEl)
@@ -94,7 +96,7 @@ describe('Popover', () => {
9496

9597
it('should set title and content from functions', () => {
9698
return new Promise(resolve => {
97-
fixtureEl.innerHTML = '<a href="#">BS twitter</a>'
99+
fixtureEl.innerHTML = '<a href="#">BS X</a>'
98100

99101
const popoverEl = fixtureEl.querySelector('a')
100102
const popover = new Popover(popoverEl, {
@@ -117,7 +119,7 @@ describe('Popover', () => {
117119

118120
it('should call content and title functions with trigger element', () => {
119121
return new Promise(resolve => {
120-
fixtureEl.innerHTML = '<a href="#" data-foo="bar">BS twitter</a>'
122+
fixtureEl.innerHTML = '<a href="#" data-foo="bar">BS X</a>'
121123

122124
const popoverEl = fixtureEl.querySelector('a')
123125
const popover = new Popover(popoverEl, {
@@ -144,7 +146,7 @@ describe('Popover', () => {
144146

145147
it('should call content and title functions with correct this value', () => {
146148
return new Promise(resolve => {
147-
fixtureEl.innerHTML = '<a href="#" data-foo="bar">BS twitter</a>'
149+
fixtureEl.innerHTML = '<a href="#" data-foo="bar">BS X</a>'
148150

149151
const popoverEl = fixtureEl.querySelector('a')
150152
const popover = new Popover(popoverEl, {
@@ -247,7 +249,7 @@ describe('Popover', () => {
247249
})
248250

249251
it('"setContent" should keep the initial template', () => {
250-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap" data-coreui-custom-class="custom-class">BS twitter</a>'
252+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap" data-coreui-custom-class="custom-class">BS X</a>'
251253

252254
const popoverEl = fixtureEl.querySelector('a')
253255
const popover = new Popover(popoverEl)
@@ -264,7 +266,7 @@ describe('Popover', () => {
264266

265267
it('should call setContent once', () => {
266268
return new Promise(resolve => {
267-
fixtureEl.innerHTML = '<a href="#">BS twitter</a>'
269+
fixtureEl.innerHTML = '<a href="#">BS X</a>'
268270

269271
const popoverEl = fixtureEl.querySelector('a')
270272
const popover = new Popover(popoverEl, {
@@ -298,7 +300,7 @@ describe('Popover', () => {
298300

299301
it('should show a popover with provided custom class', () => {
300302
return new Promise(resolve => {
301-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap" data-coreui-custom-class="custom-class">BS twitter</a>'
303+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap" data-coreui-custom-class="custom-class">BS X</a>'
302304

303305
const popoverEl = fixtureEl.querySelector('a')
304306
const popover = new Popover(popoverEl)
@@ -315,10 +317,32 @@ describe('Popover', () => {
315317
})
316318
})
317319

320+
it('should keep popover open when mouse leaves after click trigger', () => {
321+
return new Promise(resolve => {
322+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap" data-coreui-trigger="hover click">BS X</a>'
323+
324+
const popoverEl = fixtureEl.querySelector('a')
325+
new Popover(popoverEl) // eslint-disable-line no-new
326+
327+
popoverEl.addEventListener('shown.coreui.popover', () => {
328+
popoverEl.dispatchEvent(createEvent('mouseout'))
329+
330+
popoverEl.addEventListener('hide.coreui.popover', () => {
331+
throw new Error('Popover should not hide when mouse leaves after click')
332+
})
333+
334+
expect(document.querySelector('.popover')).not.toBeNull()
335+
resolve()
336+
})
337+
338+
popoverEl.click()
339+
})
340+
})
341+
318342
describe('hide', () => {
319343
it('should hide a popover', () => {
320344
return new Promise(resolve => {
321-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
345+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
322346

323347
const popoverEl = fixtureEl.querySelector('a')
324348
const popover = new Popover(popoverEl)
@@ -339,7 +363,7 @@ describe('Popover', () => {
339363

340364
describe('jQueryInterface', () => {
341365
it('should create a popover', () => {
342-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
366+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
343367

344368
const popoverEl = fixtureEl.querySelector('a')
345369

@@ -352,7 +376,7 @@ describe('Popover', () => {
352376
})
353377

354378
it('should create a popover with a config object', () => {
355-
fixtureEl.innerHTML = '<a href="#" title="Popover">BS twitter</a>'
379+
fixtureEl.innerHTML = '<a href="#" title="Popover">BS X</a>'
356380

357381
const popoverEl = fixtureEl.querySelector('a')
358382

@@ -367,7 +391,7 @@ describe('Popover', () => {
367391
})
368392

369393
it('should not re create a popover', () => {
370-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
394+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
371395

372396
const popoverEl = fixtureEl.querySelector('a')
373397
const popover = new Popover(popoverEl)
@@ -381,7 +405,7 @@ describe('Popover', () => {
381405
})
382406

383407
it('should throw error on undefined method', () => {
384-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
408+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
385409

386410
const popoverEl = fixtureEl.querySelector('a')
387411
const action = 'undefinedMethod'
@@ -395,7 +419,7 @@ describe('Popover', () => {
395419
})
396420

397421
it('should should call show method', () => {
398-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
422+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
399423

400424
const popoverEl = fixtureEl.querySelector('a')
401425
const popover = new Popover(popoverEl)
@@ -413,7 +437,7 @@ describe('Popover', () => {
413437

414438
describe('getInstance', () => {
415439
it('should return popover instance', () => {
416-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
440+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
417441

418442
const popoverEl = fixtureEl.querySelector('a')
419443
const popover = new Popover(popoverEl)
@@ -423,7 +447,7 @@ describe('Popover', () => {
423447
})
424448

425449
it('should return null when there is no popover instance', () => {
426-
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://twitter.com/getbootstrap">BS twitter</a>'
450+
fixtureEl.innerHTML = '<a href="#" title="Popover" data-coreui-content="https://x.com/getbootstrap">BS X</a>'
427451

428452
const popoverEl = fixtureEl.querySelector('a')
429453

0 commit comments

Comments
 (0)