3

This is my attempt at writing a dynamic onmouseout event that slowly changes the opacity when the mouse leaves the div. For some reason the recursion and timeout seem to be no working property and the change in opacity is done immediately.

The question: Is there any reasons that setTimeout() does not work with recursion? Is there a better way to approach this problem?

function hide(id)
{
    if (gOpacity > .4) 
    {
        gOpacity -= .1;
        document.getElementById(id).style.opacity = gOpacity;
        setTimeout(hide(id),1000)
    }
    else 
    {
        gOpacity = 1.0
    }
}
Jan Turoň
  • 31,451
  • 23
  • 125
  • 169
IntriquedMan
  • 223
  • 1
  • 7
  • 14
  • 2
    possible duplicate of [Why is the method executed immediately when I use setTimeout?](http://stackoverflow.com/questions/7137401/why-is-the-method-executed-immediately-when-i-use-settimeout) – Quentin Jun 02 '13 at 20:40
  • The answers below show the fix, but to add to the discussion, `setTimeout` works just fine recursively. setTimeout takes a function as it's first parameter, but instead, you're passing in the result of a function call. `hide(id)` invokes the function immediately. remove the (), and you're fine. – Alan Jun 02 '13 at 20:46
  • This function is essentially a "fade" out over a long period of time. Is there a reason you're not using a CSS Transition instead? On modern browsers CSS animations are hardware accelerated. – Alan Jun 02 '13 at 20:48

4 Answers4

11

Change your setTimeout call to

setTimeout(function() { hide(id); } ,1000)

So it will execute after 1s, and not immediately

BrunoLM
  • 97,872
  • 84
  • 296
  • 452
  • You beat me for 16 seconds :) – nicosantangelo Jun 02 '13 at 20:41
  • Is there anyway to cancel events like this so if the user enters and exits the div multiple times in a short time period it would cancel the prior event call? – IntriquedMan Jun 02 '13 at 20:42
  • 1
    @IntriquedMan yes. You have to store the `setTimeout` in some variable, `var x = setTimeout...` and to cancel this call use `clearTimeout(x)` http://www.w3schools.com/jsref/met_win_cleartimeout.asp – BrunoLM Jun 02 '13 at 20:43
  • Just because I'm anoying, try to avoid w3schools, MDN (for example) is way better: https://developer.mozilla.org/en-US/docs/Web/API/window.clearTimeout – nicosantangelo Jun 02 '13 at 20:45
  • @BrunoLM thanks for the help the 'clearTimeout()' works well. – IntriquedMan Jun 02 '13 at 21:06
2

Have you tried this?

function hide(id)
{
    if (gOpacity > .4) 
    {
        gOpacity -= .1;
        document.getElementById(id).style.opacity = gOpacity;
        setTimeout(function() {
           hide(id);
        },1000)
    }
    else 
    {
        gOpacity = 1.0
    }

}

nicosantangelo
  • 13,216
  • 3
  • 33
  • 47
1

i thinck that when you type :

 setTimeout(hide(id),1000);

what you really mean is :

  setTimeout(hide.bind(this,id),1000);

becasue in the first case, the function will be call instantly when setTimeout is call - it is an argument of setTimeout- .
In the second case, this will be a bound function. So yes this and id are evaluated, but the function is not called until the 1000 ms elapsed.

(this is just a faster to run / faster to type way of creating a function ).

GameAlchemist
  • 18,995
  • 7
  • 36
  • 59
1

wrap all your code in recursive function by setTimeout

function hide(id)
{
    setTimeout(function() {
        if (gOpacity > .4) 
        {
            gOpacity -= .1;
            document.getElementById(id).style.opacity = gOpacity;   
            hide(id);
        }
        else 
        {
            gOpacity = 1.0
        }
    },1000)
}
WantToDo
  • 401
  • 1
  • 5
  • 11
  • Even though your answer seems to be correct, please first read the other answers for similar answers (as there in this case is). One of the answers is also already accepted (has the green check mark next to it). – Roope Hakulinen Dec 21 '14 at 10:03