简体   繁体   中英

Bootstrap 5.2, prevent closing tooltip if cursor is back on triggering element

TLDR : moving the cursor from tooltip back to triggering element closes, shows and closes the tooltip (flickers).

I need to make the tooltips open on hover and make their content clickable. I have found a working example here on SO.

As you hover over the element it shows you a tooltip which can be interacted with, once you move the cursor away from the tooltip it closes.

There is a problem though.

If you leave the tooltip and move the cursor back on the element which triggered the tooltip, the tooltip pops back up, but dissapears after a moment ("flickering"). You need to move the cursor away from the element and back on the element for the tooltip to show again.

What I am trying to do, is check if the cursor is back on the triggering element and if that is the case not run the closing function ( tooltip.hide() ).

I have tried to do this by imitating the existing process from the example found on SO. That is, check if the tooltip has lost :hover , setTimout (300ms) and check if cursor is now positioned on the triggering element or back on the tooltip.

Here is a jsFiddle example.

This is the code. The problematic code is between the two looong comment lines.

Note: Moving the cursor away from the triggering element and back on the triggering element also triggers the flickering.


//https://stackoverflow.com/questions/67993080/bootstrap-5-make-tooltip-hoverable-and-link-clickable
var tooltipTriggerList = [].slice.call(document.querySelectorAll('button'))
for (let tt of tooltipTriggerList){
    tt.setAttribute("data-bs-placement","top")
}

var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
    const tooltip =  new bootstrap.Tooltip(tooltipTriggerEl, {
        trigger: "manual",
        'customClass': 'custom-tooltip'
    })

    let tooltipElTimeout;
    let currentToolTip;
    
    let currentTooltipTimeout;

    tooltipTriggerEl.addEventListener("mouseenter", function () {
        let toolTipID;
        
        // Clear Set Timeout
        clearTimeout(currentTooltipTimeout);
        
        // Show Tooltip
        tooltip.show();

        
        // Assign current tooltip ID to toolTipID variable
        toolTipID = tooltipTriggerEl.getAttribute("aria-describedby");

        
        // Assign current tooltip to currentToolTip variable
        currentToolTip = document.querySelector(`#${toolTipID}`);

        /*******************************************************************/
        // Hide tooltip on tooltip mouse leave
        currentToolTip.addEventListener("mouseleave", function () {
            currentTooltipTimeout = setTimeout(()=>{
                    console.log("!currentToolTip.matches(':hover')");
                    console.log(!currentToolTip.matches(":hover"));
                    if(!tooltipTriggerEl.matches(":hover")){
                        console.log("!tooltipTriggerEl.matches(':hover')");
                        console.log(!tooltipTriggerEl.matches(":hover"));
                        if (!currentToolTip.matches(":hover")) {
                            tooltip.hide();
                        }
                    }
            }, 300)
        });
  
    /***********************************************************************/

    });

    tooltipTriggerEl.addEventListener("mouseleave", function () {
      // SetTimeout before tooltip disappears
      tooltipTimeout = setTimeout(function () {
        // Hide tooltip if not hovered.
        if (!currentToolTip.matches(":hover")) {
          tooltip.hide();
        }
      }, 100);
    });

    return tooltip;

})

Thank you

Edit: Amine Ramouls answer is correct. isHidden also needs to bet set to false on the 2cnd eventListener, otherwise the tooltips no longer work (problem with aria-describedby ).

in your code you have an event listener wich add an event listner and that's a big mistake because it add an infinit number of eveneent listner to your element.

so you juste have to organize your code like this:

//https://stackoverflow.com/questions/67993080/bootstrap-5-make-tooltip-hoverable-and-link-clickable
var tooltipTriggerList = [].slice.call(document.querySelectorAll('button'))
for (let tt of tooltipTriggerList){
    tt.setAttribute("data-bs-placement","top")
}

var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
    const tooltip =  new bootstrap.Tooltip(tooltipTriggerEl, {
        trigger: "manual",
        'customClass': 'custom-tooltip'
    })
    let isHidden = true;        
    let currentTooltipTimeout;
    tooltipTriggerEl.addEventListener("mouseenter", function () {

        let toolTipID;
        // Clear Set Timeout
        clearTimeout(tooltipElTimeout);
        clearTimeout(currentTooltipTimeout);
        
        if (isHidden)
        {
                tooltip.show();
            isHidden=false;
        }
            
        
    });
        // Hide tooltip on tooltip mouse leave
    tooltipTriggerEl.addEventListener("mouseleave", function () {
                                           
                    console.log("!currentToolTip.matches(':hover')");
                    if(!tooltipTriggerEl.matches(":hover")){
                            currentTooltipTimeout=setTimeout(()=>{
                            if (!isHidden && !tooltipTriggerEl.matches(":hover")){
                                tooltip.hide();
                              isHidden=true;
                          }
                            
                            console.log("!tooltipTriggerEl.matches(':hover')");
                            console.log(!tooltipTriggerEl.matches(":hover"));
                        }, 3000)
                    }                
        });
  
    return tooltip;

})

now as you can see i juste added the isHidden var to check if the popup info is hidden or not, you can do that with the element if you can get it by a query selector request. that's it. enjoy your life.

Edit: i forget to tell you that i have put 3 seconde before checking the if the popup is hidden or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM