Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

205
Visualizações
Using setTimeout on hover interactions with a tooltip

I've got an SVG map made up of hexagons which are divided up into groups. When the user hovers over a group, I'd like to have a tooltip appear. Thing is, I want there to be like a 3 second delay to this tooltip. So if the user decides to hover off during that delay, I'd like to clear that delay to stop the tooltip from appearing as they are no longer hovering over it. There is also a delay for when the tooltip disappears as well just in case you hover over another element after quickly moving off the previous one.

I'm using setTimeout for this. What I've done here works 50% of the time but I'm finding that if I hover over and let the tooltip display, and then quickly hover over a bunch of other different elements before hovering off, the tooltip will disappear but then quickly reappear again.

Here's my code, am happy to explain anything further if needed. Cheers!

// Setting the tooltip to appear below the tooltip wrapper
gsap.set(tip, {
    yPercent: 100
});

// Tooltip Hovering Functionality with Timeouts
let hoverOutTimeout; // Timeout for hovering out

// GO through grouped elements with an event listener on mouse move, and use timeouts to delay hover
for (i = 0; i < lgas.length; i++) {
    lgas[i].onmouseover = function () {
        if (hoverOutTimeout) { // Check to see if the delay for the mouseleave function is running
            clearTimeout(hoverOutTimeout);
            //console.log("Hover back in");
        } else {
            //console.log("Hovering in");
        }

        // Set 3s delay to display tooltip
        hoverTimeout = setTimeout(function () {
            //console.log("Hovered in");

            gsap.to(tip, {
                yPercent: 0,
                ease: 'bounce.out'
            });
        }, 3000);
    }

    lgas[i].onmouseleave = function () {
        if (hoverTimeout) { // If delay to show tooltip is running, clear it
            clearTimeout(hoverTimeout);
            //console.log("Hovering back out")

            hoverOutTimeout = setTimeout(() => { // Start new delay to hide tooltip
                //console.log("Hovered out");

                gsap.to(tip, {
                    yPercent: 100,
                    ease: 'back.in'
                });
            }, 2000);

        }
        clearTimeout(hoverTimeout);
    }
}
about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

I was able to accomplish this by binding events to an associated ID. The idea is the setTimeout will check to see if it's ID is the current generated ID. The ID is generated at the time of the event binding.

On mouseenter, the event associates to the current generated ID. On mouseleave, the events are un-binded and then re-binded with a new generated ID. This approach is what prevents hovers from stacking.

I hope it sort of makes sense. I developed a snippet to experiment with.

let bindCurID;

let hoverBinder = function(){
  bindCurID = new Date() * Math.random();
  
  $('div').off('mouseenter').on('mouseenter', function(){
    let sMsg = $(this).find('h2').text();
    let bindID = bindCurID;
    
    setTimeout(function(){
      if(bindID != bindCurID)
        return
      $('body').append('<span class="hov">' + sMsg + '</span>');
    }, 2000)
    
  });
  
  $('div').off('mouseleave').on('mouseleave', function(){
    $('.hov').remove();
    hoverBinder()
  });
}

hoverBinder()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div1" style='background-color:lightblue'>
<h2>Hello</h2>
</div><br /><br />
<div id="div2" style='background-color:lightblue'>
<h2>World</h2>
</div>

I'm sure there are others out there who can do all of this in one line with some sort of wizardly tricks, but this will get the job done.

about 4 years ago · Juan Pablo Isaza Relatório

0

Some of your code is missing your post, so I took the liberty of supplying example DOM structure and generic functions for showing/hiding the tooltips. In the code below, the background color of each element will change based on whether or not the tooltip is visible. The key concept is that you need to store some state for each element (its timerId).

const SHOW_DELAY = 1500;
const HIDE_DELAY = 1200;

function showTooltip(element) {
  element.classList.add('hovered');
}

function hideTooltip(element) {
  element.classList.remove('hovered');
}

function setTooltips(elements) {
  function getMouseEventHandler(elementHandler, delay) {
    return ({target: element}) => {
      let timerId = timerIdMap.get(element) ?? 0;
      clearTimeout(timerId);
      timerId = setTimeout(() => elementHandler(element), delay);
      timerIdMap.set(element, timerId);
    };
  }

  const handleMouseEnter = getMouseEventHandler(showTooltip, SHOW_DELAY);
  const handleMouseLeave = getMouseEventHandler(hideTooltip, HIDE_DELAY);

  const timerIdMap = new WeakMap();

  for (const element of elements) {
    timerIdMap.set(element, 0);
    element.addEventListener('mouseenter', handleMouseEnter);
    element.addEventListener('mouseleave', handleMouseLeave);
  }
}

const elements = [...document.querySelectorAll('div.item')];
setTooltips(elements);
.container {
  display: flex;
  flex-wrap: wrap;
  width: 14rem;
}

.item {
  border: 1px solid;
  height: 3rem;
  width: 3rem;
}

.hovered {
  background-color: orangered;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda