Search code examples
javascripthtmlmouseover

[Plain javascript]My mouseover effect is buggy


I'm trying to achieve a mouse hover effect using Js on three <li>s.
The effect doesn't work on the first try, I have to keep hovering my mouse again and again to go back to its original string.

note: i linked the script at the right before </body>

HTML code:

<ul>
  <li data-value="// ABOUT"    ><a href="#" >// ABOUT    </a></li>
  <li data-value="// PROJECTS" ><a href='#' >// PROJECTS </a></li>
  <li data-value="// CONTACT" ><a href="#"  >// CONTACT  </a></li>
</ul>

Javascript code:

const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

let interval = null;

document.querySelectorAll("li").forEach(li => {
  li.onmouseover = event => {
    let iteration = 0;

    clearInterval(interval);

    interval = setInterval(() => {
      event.target.innerText = event.target.innerText
        .split("")
        .map((letter, index) => {
          if (index < iteration) {
            return event.target.dataset.value[index];
          }

          return letters[Math.floor(Math.random() * 26)];
        })
        .join("");

      if (iteration >= event.target.dataset.value.length) {
        clearInterval(interval);
      }

      iteration += 1 / 3;
    }, 30);
  };
});

Solution

  • 1- you don't need to use event.target because you only use arrow function.
    2- the interval variable should be local to avoid conflicts in your multiples setInterval
    3- your code remove all links -> ex <li><a href="#" >// ABOUT </a><li> by <li>// ABOUT <li>....

    so, here it is... ( with some improvemnts )

    const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    
    document.querySelectorAll('li').forEach( li_Elm => 
      {
      let interval = null
        , li_aLink = li_Elm.querySelector('a')
        , textInit = li_aLink.textContent 
        , length   = textInit.length
        ;
      li_Elm.onmouseover =_=> 
        {
        let iteration = 0;
        clearInterval(interval);
        interval = setInterval(() =>
          {
          li_aLink.textContent = Array
            .from( ({length}), (letter,index) => 
            ( index < iteration) 
                    ? textInit[index]
                    : letters[Math.floor(Math.random() * 26)]
            ).join('');
    
          if (iteration >= length)
            clearInterval(interval);
    
          iteration += 1 / 3;
          }
          , 30);
        };
      });
    <ul>
        <li><a href="#" >// ABOUT    </a></li>
        <li><a href='#' >// PROJECTS </a></li>
        <li><a href="#" >// CONTACT  </a></li>
      </ul>