Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click handler is called multiple times in jQuery animate

I am getting familiar with jQuery and making a little application where a red box moves around the screen and the user has to try and click on it and when the user does an alert() box pops up but the problem is that the alert() keeps popping up even after 'ok' is pressed. The only way I can stop it is to repeatedly click 'ok' and eventually it goes away.

Here is the code that displays the alert box:

function Animate() {
    var _newPosition = GetNewPosition();
    // Sets new position of div
    div.animate({
        top: _newPosition[0],
        left: _newPosition[1]
    }, function () {
        div.on('click', function () {
            alert('You clicked the box!');
        });
        Animate();
    });
}

Here is my JSFiddle that reproduces the problem

I originally thought that I could solve it by returning false after the call to the alert() for example:

div.on('click', function () {
    alert('You clicked the box!');
    return false;
});

But that didn't work either.

I know this should be a simple thing to figure out but I cant quite seem to get my thumb on it.

like image 988
AnonDCX Avatar asked Mar 14 '23 02:03

AnonDCX


1 Answers

The click handler is recursively called in the animation complete callback which is binding the click event on the element multiple times. So, when the element is clicked the handler is being called multiple times.

To solve the issue, bind the event only once.

function Animate() {
    var _newPosition = GetNewPosition();
    // Sets new position of div
    div.animate({
        top: _newPosition[0],
        left: _newPosition[1]
    }, Animate);
}

And in ready()

$(document).ready(function () {
    Animate();

    div.on('click', function() {
        // Code here
        alert('clicked');
    });
});

Using Animate as reference to the animation complete callback is same as

function() {
    Animate();
}

The function reference will be passed to the animate and it'll be called when the animation is completed.


Suggestions:

  1. Use mousedown event to track the click on moving object
  2. Use random duration for animate.

FIddle

var div = $('#box');
$(document).ready(function() {
  Animate();

  div.on('mousedown', function() {
    // Code here
    console.log('clicked');
  });
});

function GetNewPosition() {
  // Get dimentions of the window and remove the div area
  var h = $(window).height() - 50;
  var w = $(window).width() - 50;
  // New height and width is auto generated
  var nh = Math.floor(Math.random() * h);
  var nw = Math.floor(Math.random() * w);
  return [nh, nw];
}

function Animate() {
  var _newPosition = GetNewPosition();
  // Sets new position of div
  div.animate({
    top: _newPosition[0],
    left: _newPosition[1]
  }, (Math.floor(Math.random() * 5000) + 1), Animate);
}
#box {
  width: 50px;
  height: 50px;
  background-color: red;
  position: fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3 id="success"></h3>
<div id="box"></div>
like image 179
Tushar Avatar answered Mar 24 '23 14:03

Tushar