Atheneor
Atheneor

Reputation: 51

Stop function on mouseout | JS

I've built the following function, which changes the content of a span on mouseover. Everything works fine. The only problem is that I'm not sure how to stop the function on mouseout (initial and mouseout state should be the same).

Here is my current solution.

var squWrd = document.getElementById("squWrd");
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

squWrd.onmouseover = function () {
    squWrd.innerHTML = "Design.";
    sleep(250).then(() => { squWrd.innerHTML = "UX."; });
    sleep(500).then(() => { squWrd.innerHTML = "Marketing."; });
    sleep(750).then(() => { squWrd.innerHTML = "Social Media."; });
    sleep(1000).then(() => { squWrd.innerHTML = "Education."; });
    sleep(1250).then(() => { squWrd.innerHTML = "Branding."; });
    sleep(1500).then(() => { squWrd.innerHTML = "Packaging."; });
    sleep(1750).then(() => { squWrd.innerHTML = "Design."; });
    sleep(2000).then(() => { squWrd.innerHTML = "Processes."; });
    sleep(2250).then(() => { squWrd.innerHTML = "E-Commerce."; });
    sleep(2500).then(() => { squWrd.innerHTML = "Advertising."; });
    sleep(2750).then(() => { squWrd.innerHTML = "Photos."; });
    sleep(3000).then(() => { squWrd.innerHTML = "Products."; });
    sleep(3250).then(() => { squWrd.innerHTML = "Logos."; });
    sleep(3500).then(() => { squWrd.innerHTML = "Emotions."; });
    sleep(3750).then(() => { squWrd.innerHTML = "Solutions."; });
}

squWrd.onmouseout = function () {
    squWrd.innerHTML = "Solutions.";
}

Do you guys have any suggestions? Thanks in advance!

Upvotes: 2

Views: 264

Answers (2)

lissettdm
lissettdm

Reputation: 13078

Timeouts are still running, you need to call clearTimeout. I recommend you to add a second argument to the sleep function, a callback function that pass the timeout reference, this way you can clear only the timeouts related to the texts and not all the timers.

Also instead of call sleep for every text, you can store this texts inside an array an iterate over it:

var squWrd = document.getElementById("squWrd");


function sleep(ms, cb=()=> {}) {
  return new Promise(resolve => {
    const time = setTimeout(() => {
      resolve();
    }, ms);
    cb(time);
  });
}

const texts = ["Design", "UX.", "Marketing.", "Social Media.", "Education.", "Branding.", "Packaging.", "Design.", "Processes.", "E-Commerce.", "Advertising.", "Photos.", "Products.", "Logos.", "Emotions.", "Solutions."];

const textTimeouts = [];

squWrd.onmouseover = function() {
  texts.forEach((text, i) => {
    sleep(250 * i, (time) => textTimeouts.push(time)).then(res => {
      squWrd.innerHTML = text;
    });
  });
};

squWrd.onmouseout = function() {
  squWrd.innerHTML = "Solutions.";
  textTimeouts.forEach(time => clearTimeout(time));
};
<h1 id="squWrd">Solutions</h1>

Upvotes: 2

Alyson Maia
Alyson Maia

Reputation: 810

The problem is that even when onmouseout gets triggered, there are still sleep promises pending. You need to save the reference for each setTimeout call and clear it at onmouseout event. See here.

var squWrd = document.getElementById('squWrd');
var timeoutRefs = [];

function sleep(ms) {
  return new Promise(resolve => timeoutRefs.push(setTimeout(resolve, ms)));
}

squWrd.onmouseover = function () {
  squWrd.innerHTML = "Design.";
  sleep(250).then(() => { squWrd.innerHTML = "UX."; });
  sleep(500).then(() => { squWrd.innerHTML = "Marketing."; });
  sleep(750).then(() => { squWrd.innerHTML = "Social Media."; });
  sleep(1000).then(() => { squWrd.innerHTML = "Education."; });
  sleep(1250).then(() => { squWrd.innerHTML = "Branding."; });
  sleep(1500).then(() => { squWrd.innerHTML = "Packaging."; });
  sleep(1750).then(() => { squWrd.innerHTML = "Design."; });
  sleep(2000).then(() => { squWrd.innerHTML = "Processes."; });
  sleep(2250).then(() => { squWrd.innerHTML = "E-Commerce."; });
  sleep(2500).then(() => { squWrd.innerHTML = "Advertising."; });
  sleep(2750).then(() => { squWrd.innerHTML = "Photos."; });
  sleep(3000).then(() => { squWrd.innerHTML = "Products."; });
  sleep(3250).then(() => { squWrd.innerHTML = "Logos."; });
  sleep(3500).then(() => { squWrd.innerHTML = "Emotions."; });
  sleep(3750).then(() => { squWrd.innerHTML = "Solutions."; });
};

squWrd.onmouseout = function () {
  timeoutRefs.forEach(function (timeoutRef) {
    clearTimeout(timeoutRef)
  });
  timeoutRefs = [];
  squWrd.innerHTML = 'Solutions.';
};
<div id="squWrd">INITIAL VALUE</div>

Upvotes: 2

Related Questions