0

Ok, so i have this code, adding a method (from what i understand) to the HTML element prototype:

HTMLElement.prototype.fadeIn = function( seconds ) {

var self = this;
var miliseconds = seconds * 1000;
var hold = this.style.transition;
this.style.transition = "opacity " + seconds + "s ease";
this.style.opacity = 1;

setTimeout(
    function () {
        self.style.transition = hold;
        return self;
    },
miliseconds);

};

my intention is that, at the end of the timeout, the function will return the instance of the HTMLElement so i can chain the fadeIn function with another one.

However it does not, and doing a console.log to what it returns, it says it's undefined. Can anyone give some advice as to how can i do this?

Klimid1689
  • 111
  • 1
  • 3
  • 9

2 Answers2

0

setTimeout() is an asynchronous operation. It does not "pause" the execution of your fadeIn() function. Your .fadeIn() method returns immediately and then the timer operation happens afterwards.

Returning self from the setTimeout() callback does nothing useful. It just returns self into the inner bowels of the timer subsystem where it is dutifully ignored.

You can support chaining from your .fadeIn() operation by just adding a return this; to the end of your method:

HTMLElement.prototype.fadeIn = function( seconds ) {
    var self = this;
    var miliseconds = seconds * 1000;
    var hold = this.style.transition;
    this.style.transition = "opacity " + seconds + "s ease";
    this.style.opacity = 1;

    setTimeout(
        function () {
            self.style.transition = hold;
        }, miliseconds);
    return this;
};

But, this won't tell you anything about when the fade operation is actually complete. If you want to know that, you will have to design something else into your method (a callback or a promise or a queue) in order to support animation chaining.


If you're trying to do animation chaining like jQuery does so you could do this:

obj.fadeIn(5).fadeOut(5);

and the two animations would happen in sequence, then a more complicated system will be required. jQuery uses an animation queue where an animation is not necessarily executed immediately, but rather it's added to a queue that is specific to that particular DOM object. Whenever an animation for that particular object completes, it then looks in its queue to see if there's another animation waiting to go for this same object. If so, it starts that animation.

Also, if you're using CSS3 animations and you need to know when the animation is complete, you would need to register for the transitionend event on the object.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

You can't return something after the timeout, because the heraclitan stream has moved on: Where are you going to return too?

One simple way of chaining functions that have delays is to pass them in:

HTMLElement.prototype.fadeIn = function(seconds, continueWith) {
var self = this;
var miliseconds = seconds * 1000;
var hold = this.style.transition;
this.style.transition = "opacity " + seconds + "s ease";
this.style.opacity = 1;
setTimeout(
    function () {
        self.style.transition = hold;
        if(continueWith)
          continueWith();
    },
miliseconds);
};

You could call this with el.fadeIn(1.5, function(){el.fadeOut(2);}); and then fadeOut would be called after fadeIn had completed.

You could also return a promise object:

function createTimeoutPromise(timeOut)
{
    var promise = 
    {
        toRun: null,
        continueWith: function(func)
        {
            this.toRun = func;
        }
    }
    setTimeout(function()
    {
        if(promise.toRun)
            promise.toRun();
    }, timeOut);
    return promise;
}

HTMLElement.prototype.fadeIn = function(seconds)
{
    var self = this;
    var miliseconds = seconds * 1000;
    var hold = this.style.transition;
    this.style.transition = "opacity " + seconds + "s ease";
    this.style.opacity = 1;
    return createTimeoutPromise(miliseconds);
};

You could then call this with You could call this with el.fadeIn(1.5).continueWith(function(){el.fadeOut(2);}); which can be a nicer chaining style.

Note that in both cases we check for the case of there being no function to continue with, so that the end of the chain doesn't cause an error.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251