CKY
CKY

Reputation: 35

Remove div after fade out animation - javascript

I'm trying to remove a div from the body AFTER an animation is completed, but at the moment looks like the remove happens right after the first iteration of the animation.

function $(el) { return document.getElementById(el); }

var divFirst = $('first');
if(divFirst)
    divFirst.addEventListener("click", addSecond);

function removeSecond()
{
    fadeOut();
    var child = $('second');
    console.log("remove called");
    child.remove();
}

function addSecond()
{
    console.log("addSecond called");
    var aContainer = document.createElement('div');
    aContainer.setAttribute('id', 'second');
    aContainer.innerHTML = "Second";
    aContainer.addEventListener("click", removeSecond);
    document.body.appendChild(aContainer);
    fadeIn();
}

function fadeIn()
{
    var secondDiv = $('second');
    if(secondDiv)
    {
        secondDiv.style.opacity ? secondDiv.style.opacity : 
            secondDiv.style.opacity = "0.0";
        if(parseFloat(secondDiv.style.opacity) <= 1)
        {
            secondDiv.style.opacity = parseFloat(secondDiv.style.opacity) + 0.05;
            setTimeout(fadeIn, 50);
        }
    }
}

function fadeOut()
{
    var secondDiv = $('second');
    if(secondDiv)
    {
        console.log(secondDiv.style.opacity);
        if(parseFloat(secondDiv.style.opacity) >0 )
        {
            secondDiv.style.opacity = parseFloat(secondDiv.style.opacity) - 0.05;
            setTimeout(fadeOut, 50);
        }
    }
}

Here the jsfiddle: http://jsfiddle.net/ny85ckk2/ If I remove the child.remove() call, the animation continues till the end. Any idea?

Thanks a lot

Upvotes: 0

Views: 706

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074989

Your fadeOut is an asynchronous operation. When you call it, it starts the fade, but then the fade continues and completes asynchronously because you're using setTimeout. So your code after callilng fadeOut runs just after it starts.

To remove the element when done, remove that code and instead remove the element in fadeOut when done:

function fadeOut()
{
    var secondDiv = $('second');
    if(secondDiv)
    {
        console.log(secondDiv.style.opacity);
        if(parseFloat(secondDiv.style.opacity) >0 )
        {
            secondDiv.style.opacity = parseFloat(secondDiv.style.opacity) - 0.05;
            setTimeout(fadeOut, 50);
        }
        else                         // Added
        {                            // Added
            secondDiv.remove();      // Added
        }                            // Added
    }
}

Or if you want more flexibility, have fadeOut call a callback when done and remove the element in the callback; we do that by separating out the actual work of the fade from starting it:

function fadeOut(callback)
{
    var secondDiv = $('second');
    if (secondDiv)
    {
        doFade();
    }

    function doFade() {
        if(parseFloat(secondDiv.style.opacity) >0 )
        {
            secondDiv.style.opacity = parseFloat(secondDiv.style.opacity) - 0.05;
            setTimeout(doFade, 50);
        }
        else if (callback)
        {
            callback(secondDiv);
        }
    }
}

Usage:

function removeSecond()
{
    fadeOut(function(div) {
        div.remove();
    });
}

Fiddle

Upvotes: 1

Related Questions