]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
only trigger tooltip inserted event on true dom insert
authorRyan Berliner <ryan.berliner@gmail.com>
Sun, 7 Mar 2021 15:09:17 +0000 (17:09 +0200)
committerXhmikosR <xhmikosr@gmail.com>
Tue, 16 Mar 2021 05:48:50 +0000 (07:48 +0200)
js/src/tooltip.js
js/tests/unit/tooltip.spec.js

index de7dcca69391ede0898b3c30467cf5a2f3530517..979bd077382ce2afec57726cefc592384047d0f6 100644 (file)
@@ -279,10 +279,9 @@ class Tooltip extends BaseComponent {
 
     if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
       container.appendChild(tip)
+      EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
     }
 
-    EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
-
     if (this._popper) {
       this._popper.update()
     } else {
index 1cb301c151aa331443b57bcc360abff8eb1d113c..f9d97e3f7ed4120d7db4e6e9bd6e69c1dd36c15d 100644 (file)
@@ -708,6 +708,37 @@ describe('Tooltip', () => {
       tooltipEl.dispatchEvent(createEvent('mouseover'))
     })
 
+    it('should not hide tooltip if leave event occurs and interaction remains inside trigger', done => {
+      fixtureEl.innerHTML = [
+        '<a href="#" rel="tooltip" title="Another tooltip">',
+        '<b>Trigger</b>',
+        'the tooltip',
+        '</a>'
+      ]
+
+      const tooltipEl = fixtureEl.querySelector('a')
+      const tooltip = new Tooltip(tooltipEl)
+      const triggerChild = tooltipEl.querySelector('b')
+
+      spyOn(tooltip, 'hide').and.callThrough()
+
+      tooltipEl.addEventListener('mouseover', () => {
+        const moveMouseToChildEvent = createEvent('mouseout')
+        Object.defineProperty(moveMouseToChildEvent, 'relatedTarget', {
+          value: triggerChild
+        })
+
+        tooltipEl.dispatchEvent(moveMouseToChildEvent)
+      })
+
+      tooltipEl.addEventListener('mouseout', () => {
+        expect(tooltip.hide).not.toHaveBeenCalled()
+        done()
+      })
+
+      tooltipEl.dispatchEvent(createEvent('mouseover'))
+    })
+
     it('should properly maintain tooltip state if leave event occurs and enter event occurs during hide transition', done => {
       // Style this tooltip to give it plenty of room for popper to do what it wants
       fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip" data-bs-placement="top" style="position:fixed;left:50%;top:50%;">Trigger</a>'
@@ -740,6 +771,37 @@ describe('Tooltip', () => {
       tooltipEl.dispatchEvent(createEvent('mouseover'))
     })
 
+    it('should only trigger inserted event if a new tooltip element was created', done => {
+      fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
+
+      const tooltipEl = fixtureEl.querySelector('a')
+      const tooltip = new Tooltip(tooltipEl)
+
+      spyOn(window, 'getComputedStyle').and.returnValue({
+        transitionDuration: '0.15s',
+        transitionDelay: '0s'
+      })
+
+      const insertedFunc = jasmine.createSpy()
+      tooltipEl.addEventListener('inserted.bs.tooltip', insertedFunc)
+
+      setTimeout(() => {
+        expect(insertedFunc).toHaveBeenCalledTimes(1)
+        tooltip.hide()
+
+        setTimeout(() => {
+          tooltip.show()
+        }, 100)
+
+        setTimeout(() => {
+          expect(insertedFunc).toHaveBeenCalledTimes(1)
+          done()
+        }, 200)
+      }, 0)
+
+      tooltip.show()
+    })
+
     it('should show a tooltip with custom class provided in data attributes', done => {
       fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip" data-bs-custom-class="custom-class">'