user4501876
user4501876

Reputation: 41

Javascript will not wait for JQuery animation to finish before executing next command

I'm trying to create a simple 2-D game in Javascript. I'm going to use jQuery to do some animations.

There will be buttons that a player will use to call various functions (Move up/down/left/right, Attack, Defend, etc).

A movement() function will call a secondary function, animateCharacter(), to handle the movement of an image object on screen.

The problem I'm having is that the next command in the movement() function executes before the animateCharacter() function has finished.

I tried to add a callback function, but that didn't fix the situation. I've tried many other things -- setInterval, setTimeout, .delay, etc. Nothing seems to fix this situation. What am I not doing, or what am I doing wrong?

Here's a simplified example of the problem....

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  
<style>
	#mainContainer {
		border: 1px solid gray;
		width:100px;
		height:100px;
		position: relative;
	}
	#myObject {
		border: 1px solid gray;
		width: 30px;
		height: 30px;
		color:blue;
		text-align:center;
		background-color:yellow;
		position:relative;
	}
</style>
</head>
<body>
<div id="mainContainer">
	<div id="myObject">:c)</div>
</div>
<script>
	// MOVE THE BLOCK TO THE RIGHT
	function animateCharacter(callbackSent) {
		$("#myObject").animate({left: "+=50"},1500, function () { callbackSent();});
	}
	
	// DO THIS WHEN THE BUTTON IS PUSHED
	function doTask() {
		myCallback = function () { document.getElementById("mainContainer").innerHTML = "hello"; };
		animateCharacter(myCallback);
        // WORKS FINE IF THIS IS COMMENTED OUT, 
        // BUT I WANT MORE CODE TO EXECUTE
		document.getElementById("mainContainer").innerHTML = "goodbye"; 
	}	
</script>
<button id="pushMe" onclick="doTask();">Move the Block</button>

</body>
</html>

Upvotes: 2

Views: 1363

Answers (4)

guest271314
guest271314

Reputation: 1

Try

function animateCharacter() {
  return $("#myObject").animate({
    left: "+=50"
  }, 1500, function() {
        $(this)
        .fadeOut(500)
        .parent()
        .html("<span>hello</span>")
        .find("span")
        .delay(1500, "fx")
        .fadeOut(250, function() {
          $(this).html("Goodbye").fadeIn(250)
        })
  })
}

$("#pushMe").on("click", function() {
  animateCharacter()
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
  <style>
    #mainContainer {
      border: 1px solid gray;
      width: 100px;
      height: 100px;
      position: relative;
    }
    #myObject {
      border: 1px solid gray;
      width: 30px;
      height: 30px;
      color: blue;
      text-align: center;
      background-color: yellow;
      position: relative;
    }
  </style>
</head>
<body>
  <div id="mainContainer">
    <div id="myObject">:c)</div>
  </div>
  <button id="pushMe">Move the Block</button>
</body>
</html>

Upvotes: 0

Maurice Perry
Maurice Perry

Reputation: 32831

You can't put your "goodbye" message directly in #myContainer because this will destroy #myObject. Add another div to hold the message:

HTML:

<div id="mainContainer">
    <div id="myObject">:c)</div>
    <div id="myText"></div>
</div>

CSS:

#myText {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
}

JavaScript:

function doTask() {
    myCallback = function () { document.getElementById("mainContainer").innerHTML = "hello"; };
    animateCharacter(myCallback);
    // WORKS FINE IF THIS IS COMMENTED OUT, 
    // BUT I WANT MORE CODE TO EXECUTE
    document.getElementById("myText").innerHTML = "goodbye";
}   

Fiddle here: http://jsfiddle.net/robbyn/0qkt0v5r/

Upvotes: 0

Puneet
Puneet

Reputation: 2051

Try This.

Moved document.getElementById("mainContainer").innerHTML = "goodbye"; to the setTimeout function, that will execute after Hello is printed in the div.

Your code was executing like:

  1. Animate the box with 1500 miliseconds - Animation starts
  2. Change main content to goodBye without waiting for animation completion - Right after animation start
  3. Animation got Completed, so change content to Hello - Animation Completes, though the user never saw it.

// MOVE THE BLOCK TO THE RIGHT
	function animateCharacter(callbackSent) {
		$("#myObject").animate({left: "+=50"},1500, callbackSent);
	}
	
	// DO THIS WHEN THE BUTTON IS PUSHED
	function doTask() {
		myCallback = function () { document.getElementById("mainContainer").innerHTML = "hello";
                                  setTimeout(function(){document.getElementById("mainContainer").innerHTML = "goodbye"; },1000);
                                 };
		animateCharacter(myCallback);
        // WORKS FINE IF THIS IS COMMENTED OUT, 
        // BUT I WANT MORE CODE TO EXECUTE
		
	}	
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  
<style>
	#mainContainer {
		border: 1px solid gray;
		width:100px;
		height:100px;
		position: relative;
	}
	#myObject {
		border: 1px solid gray;
		width: 30px;
		height: 30px;
		color:blue;
		text-align:center;
		background-color:yellow;
		position:relative;
	}
</style>
</head>
<body>
<div id="mainContainer">
	<div id="myObject">:c)</div>
</div>

<button id="pushMe" onclick="doTask();">Move the Block</button>

</body>
</html>

Upvotes: 1

iCollect.it Ltd
iCollect.it Ltd

Reputation: 93571

Your code does what it is told at the moment. You need to introduce a delay before showing goodbye.

// MOVE THE BLOCK TO THE RIGHT
function animateCharacter(callbackSent) {
    $("#myObject").animate({
        left: "+=50"
    }, 1500, callbackSent);
}

// DO THIS WHEN THE BUTTON IS PUSHED
function doTask() {
    animateCharacter(function () {
        $("#mainContainer").html("hello");
        setTimeout(function () {
            $("#mainContainer").html("Goodbye");
        }, 3000);
    });
}

$('#pushMe').click(doTask);

JSFiddle: http://jsfiddle.net/TrueBlueAussie/7tucg2s5/1/

Notes:

  • I also used jQuery alternatives to shorten the code.
  • I moved your inline onclick handler to the jQuery equivalent as that is easier to maintain.

Upvotes: 1

Related Questions