1

I'm writing a small script who, on mouse hover, add class and on mouse leave remove class. Remove must be with delay.

Following script just addClass and don't work on removeClass. I don't get error...

$(".result").hover(
  function () {
    $(this).addClass("current");
  },
  function () {
    setTimeout( function () {
        $(this).removeClass("current");
    }, 800)
  }
);

The same script, but withouth setTimeout, work...

$(".result").hover(
  function () {
    $(this).addClass("current");
  },
  function () {
    $(this).removeClass("current");
  }
);

Can anyone help me?

Thanks!

Brisk
  • 77
  • 14
  • 3
    I assume it's a problem to do with `this` reverting the global object inside the callback (although I'm surprised because I've not come across this with jQuery and thought it must hard-bind the `this` to prevent this problem). If so, you can fix it with an arrow function: `setTimeout(() => $(this).removeClass("current"), 800)` – Robin Zigmond Feb 18 '19 at 10:33
  • 2
    Alternatively, if you can;t use arrow functions you could try doing something like `var _this = this; setTimeout(function () { $(_this). ...` – Ben Lonsdale Feb 18 '19 at 10:34
  • @RobinZigmond the arrowed function work fine! Thanks! – Brisk Feb 18 '19 at 10:45
  • @BenLonsdale i tried but seems don't work... thanks anyway! – Brisk Feb 18 '19 at 10:46

1 Answers1

3

Inside the setTimeout the context of this is different. In that case you can use the arrow function () as shown in example two or use .bind to bind the scope to the current context

$(".result").hover(
  function() {
    $(this).addClass("current");
  },
  function() {
    setTimeout(function() {
      $(this).removeClass("current");
    }.bind(this), 800)
  });

// with arrow function

$(".result2").hover(
  function() {
    $(this).addClass("current2");
  },
  function() {
    setTimeout(() => {
      $(this).removeClass("current2");
    }, 800)
  });
.current {
  color: red;
}

.current2 {
  color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='result'> I am the result </div>

<div class='result2'> I am the result2 </div>
brk
  • 43,022
  • 4
  • 37
  • 61
  • 1
    @Brisk careful with arrow functions though, not supported in all browsers. You could also just use `.bind(this)` – TKoL Feb 18 '19 at 10:48
  • It's supported in any browser less than 4-5 years old - which in practice means everything anyone actually uses, with the inevitable exception of IE. (I have no idea why people still use IE, but apparently many do.) – Robin Zigmond Feb 18 '19 at 10:51
  • @TKoL oh thanks for the tip! Changed the script with .bind! – Brisk Feb 18 '19 at 11:25
  • 1
    @RobinZigmond why people still use IE? Is a huge mistery! – Brisk Feb 18 '19 at 11:25