kom
kom

Reputation: 135

jQuery event handling with .live() problem with setInterval and clearInterval

jQuery 1.4.2:

I have an image. When the mouseover event is triggered, a function is executed that runs a loop to load several images. On the contrary, the mouseout event needs to set the image back to a predetermined image and no longer have the loop executing. These are only for the images with class "thumb":

$("img.thumb").live("mouseover mouseout", function(event) {
    //var foo = $(this).attr('id');
    var wait;
    var i=0;
    var image = document.getElementById(foo);

    if (event.type == 'mouseover') {
        function incrementimage()
        {
            i++;
            image.src = 'http://example.com/images/file_'+i+'.jpg';
            if(i==30) {i=0;}
        }    
        wait = setInterval(incrementimage,500);
    } else if (event.type == 'mouseout') {
        clearInterval (wait);
        image.src = 'http://example.com/images/default.jpg';
    }
    return false;
});

When I mouseout, the image is set to the default.jpg but the browser continues to loop though the images. It will never stop. Can someone hit me with some knowledge? Thanks.

Upvotes: 1

Views: 1265

Answers (3)

Nick Craver
Nick Craver

Reputation: 630627

You can shorten your code down to this to clear the interval properly:

$("img.thumb").live("mouseover", function() {
  var i = 0, image = this, incrementimage = function() {
    i++;
    image.src = 'http://example.com/images/file_'+i+'.jpg';
    if(i==30) {i=0;}
  };
  $(this).data('timer', setInterval(incrementimage,500));
}).live("mouseout", function() {
  clearInterval($(this).data('timer'));
  this.src = 'http://example.com/images/default.jpg';
});

This splits the .live() calls to make the logic a bit cleaner, and stores the previous wait id on the element itself using .data() instead of as a global variable.

Upvotes: 2

cletus
cletus

Reputation: 625427

The problem is that the mouseout event doesn't see the same wait that the mouseover event did. You need to store it somewhere else. I would suggest using [data()][1] to store it on the element.

Also, this sequence doesn't make sense:

var foo = $(this).attr('id');
...
var image = document.getElementById(foo);

this is already the image element.

Lastly, that's not how I'd define the function. Try something like:

$("img.thumb").live("mouseover", function(evt) {
  var wait = $(this).data("wait");
  if (!wait) {
    clearInterval(wait);
  }
  var i = 0;
  var image = this;
  var incrementImage = function() {
    i++;
    image.src = "http://example.com/images/file_" + i + ".jpg";
    if (i == 30) {
      i = 0;
    }
  }
  wait = setInterval(incrementImage, 500);
  $(this).data("wait", wait);
  return false;
});

$("img.thumb").live("mouseout", function(event) {
  var wait = $(this).data("wait");
  if (wait) {
    clearInterval(wait);
  }
  img.src = "http://example.com/default.jpg";
  return false;
});

Upvotes: 1

gurun8
gurun8

Reputation: 3556

Have you tried moving your var wait outside your .live() event?

var wait
$("img.thumb").live("mouseover mouseout", function(event) {

Upvotes: 0

Related Questions