Hive7
Hive7

Reputation: 3675

setInterval() inside plugin function not being called

I have a jQuery slideshow plugin that I am making though it has a setInterval() inside it which is not being called though if I move the contents of the setInterval() outside of the it then it works though it only runs once.

var gap = 3;
var duration = 0.5;
(function ($) {
    $.fn.slideshow = function () {
        return this.each(function () {
            g = gap * 1000;
            d = duration * 1000;
            $(this).children().css({
                'position': 'absolute',
                'display': 'none'
            });
            $(this).children().eq(0).css({
                'display': 'block'
            });
            setInterval(function () {
                slide();
            }, g);

            function slide() {
                $(this)
                    .children()
                    .eq(0)
                    .fadeOut(d)
                    .next()
                    .fadeIn()
                    .end()
                    .appendTo($(this).children().eq(0).parent());
            }
        });
    };
})(jQuery);
$('.slideshow').slideshow();

HTML:

<div class='slideshow'>
    <a>1</a>
    <a>2</a>
    <a>3</a>
    <a>4</a>
</div>

Here is a fiddle with my plugin:

http://jsfiddle.net/Hive7/GrtLC/

Upvotes: 2

Views: 904

Answers (4)

Kete
Kete

Reputation: 70

this inside slide function is not the slideshow. I make it work caching the object inside the each loop: http://jsfiddle.net/x7Jk8/

Upvotes: 0

Blazemonger
Blazemonger

Reputation: 92903

Your problem is that this is always locally defined; by the time you get into the setInterval(), you've lost your original this (it's reset to the window object).

There are a few ways to get around this; the simplest is probably to copy this into a local variable.

http://jsfiddle.net/mblase75/GrtLC/5/

var gap = 3;
var duration = 0.5;
(function ($) {
    $.fn.slideshow = function () {
        return this.each(function () {
            g = gap * 1000;
            d = duration * 1000;
            $this = $(this); // caches the jQuery object as a further optimization
            $this.children().css({
                'position': 'absolute',
                'display': 'none'
            });
            $this.children().eq(0).css({
                'display': 'block'
            });
            setInterval(function () {
                slide($this); // pass $this into the function
            }, g);

            function slide($obj) {
                $obj.children()
                    .eq(0)
                    .fadeOut(d)
                    .next()
                    .fadeIn()
                    .end()
                    .appendTo($obj.children().eq(0).parent());
            }
        });
    };
})(jQuery);
$('.slideshow').slideshow();

Upvotes: 1

Your code cannot work, because your callback is not bound to the this; try instead

var that = this;

setInterval(function () {
    slide();
}, g);

function slide() {
    $(that) ....

Upvotes: 0

Arun P Johny
Arun P Johny

Reputation: 388316

The problem is this inside the slider function does not point to the object you think it points to.

        setInterval($.proxy(function () {
            slide.call(this);
        }, this), g);

Demo: Fiddle

or better

setInterval($.proxy(slide, this), g);

Demo: Fiddle

Upvotes: 5

Related Questions