0

I have this html code

<p id = "line1"> You are in a field </p>
<button id = "btn1"> [ Go to cave ] </button>

and this javascript code using jQuery

var bar = 0;  
$(document).ready(function(){
    $("#btn1").click(function(){
        console.log("Going to cave entrance");
        bar = 1;
    });
    if (bar){
        console.log("At entrance");
        $("#line1").html("Go into cave?");
        $("#btn1").html("Yes!!");
     }
     else{
        console.log("I am error");
     }
 });

As you can see I have a button that sets the variable bar to 1 and an if statement that is waiting for bar to be 1. However, when I click on the button, the if statement never executes.

The variable bar is set to 1 and console.log("Going to cave entrance") prints, but nothing else is executed.

It is like the execution is stuck in the .click() function.

prabhat gundepalli
  • 907
  • 3
  • 15
  • 39
Kasper
  • 63
  • 5
  • `if` is executed on `document.ready` (before the button is clicked), so there is no `bar`… – helb Nov 26 '18 at 20:57
  • Your `if` logic only runs once, when the document is ready. When is it supposed to run? – Scott Marcus Nov 26 '18 at 20:58
  • 1
    Note that fixing this will not prevent this game setup from turning into an if-else nightmare. I recommend either using an actual IF engine like Inform or learning a lot more about the JS toolbox besides the two tools you've mastered so far. (also, there's no asynchronous code here, and this is by no means a duplicate of that other question...) –  Nov 26 '18 at 21:01
  • Add a separate function for the `if statement` and run it whenever the button is clicked [like this](http://jsfiddle.net/3Lb5wkvm/). Would have posted it as an answer but Quentin closed the question unfortunately. – AndrewL64 Nov 26 '18 at 21:04
  • @ChrisG Agreed. I have voted to re-open this question. – AndrewL64 Nov 26 '18 at 21:04
  • @ChrisG — The callback to the click handler runs asynchronously. It fires when the click happens, not immediately. The problem here is the same timing problem as in [the duplicate](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call). – Quentin Nov 26 '18 at 21:07
  • 1
    @Quentin I can see where you're coming from; it's a similar problem. However I also think that the OP will not understand what the issue is from that other question but rather become even more confused. The accepted answer begins with AJAX, mentions async and promises, and is multiple pages long. How is that going to help somebody who doesn't understand event based programming? –  Nov 26 '18 at 21:12
  • 1
    @Quentin The callback doesn't happen asynchronously. It happens later. But when it does, it happens synchronously. – Scott Marcus Nov 26 '18 at 21:14
  • AndrewL's answer makes a lot of sense to me (coming from my own coding experience, granted I don't have much experience with javascript at the moment) – Kasper Nov 26 '18 at 21:16
  • 1
    @Kasper But, even if you do that, you've got a logic problem. When you click the button, you set your variable to `1`, so there's no need to immediately call another function that tests to see if it's non-zero. You're missing something here. The `if` test should be wrapped in a function, but the function should be called at some other time, not right after the button has been clicked. The real question here is when is that other time? – Scott Marcus Nov 26 '18 at 21:19
  • @ScottMarcus My idea what to make a hub area where the player can move back and forth to different areas collecting items. I need to keep track of what area they are in the game and display the appropriate text. But I understand what you mean, checking immediately if bar = 1 doesn't solve the question. – Kasper Nov 26 '18 at 21:31
  • @Kasper See my updated/expanded answer that deals with you last comment. – Scott Marcus Nov 26 '18 at 21:47

3 Answers3

2

Your statement run one time in load.

so move if - else into btn click event

var bar = 0;

$(document).ready(function(){

    $("#btn1").click(function(){
        console.log("Going to cave entrance");
        bar = 1;
        if (bar){
            console.log("At entrance");
            $("#line1").html("Go into cave?");
            $("#btn1").html("Yes!!");

         }
         else{
            console.log("I am error");
         }
    });
 });
Yashar Panahi
  • 2,816
  • 1
  • 16
  • 22
2

In short, your if logic is running as soon as the DOM is ready (which is before the user gets a chance to click your button) because you've placed it directly inside of JQuery's document.ready callback function:

$(document).ready(function(){
  // Anything here will execute one time, when the DOM is fully parsed
});

In order for that if logic to be run at some point after the button is clicked, it will need to be placed into a function that can be called whenever you want it to be:

function testButton(){
  if (bar){
    console.log("At entrance");
    $("#line1").html("Go into cave?");
    $("#btn1").html("Yes!!");
  } else{
    console.log("I am error");
  }
}

But, the real question is when should this function run? It doesn't make sense for it to run right after the button is clicked because in the click event handler for the button, the bar variable is manually set to 1. If you call your testing function right after the click, it will always enter the true branch of your test.

If you're looking to find a way to keep track of places the player has been, a better approach would be to set up an array of those places and check the array as the user moves around.

So, in the end, you'll want to set up your code like the following:

var visitedPlaces = [];  // Store visited places here

$(document).ready(function(){
  // When any of the location change buttons get clicked...
  $(".changeLocation").click(function(){
    // Extract the location from the data-* attribute of the clicked button 
    var newLocation = $(this).data("location");
    
    // Test to see if player has already gone here
    if (testLocation(newLocation)){
      console.log("You've already been to the " + newLocation + "!");
    } else {
      console.log("Entering " + newLocation + "!");
    }
    
    visitedPlaces.push(newLocation); // Record that player has been to cave
  });
});

// Call this function anytime you need to test the bar variable:
function testLocation(loc){
  // Check if the location is already in the array and return true/false as appropriate
  return (visitedPlaces.indexOf(loc) > -1) ? true : false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id = "line1"> You are in a field </p>
<!-- Use data-* attributes to signal where the user is going -->
<button class="changeLocation" data-location="cave">[ Go to cave ]</button>
<button class="changeLocation" data-location="inn">[ Go to inn ]</button>
<button class="changeLocation" data-location="mountains">[ Go to mountains ]</button>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

Add a separate function for the if statement and run it whenever the button is clicked like this:

var bar = 0;

$(document).ready(function(){

    $("#btn1").click(function(){
        console.log("Going to cave entrance");
        bar = 1;
        checkBar();
    });
  
    function checkBar() {
      if (bar){
          console.log("At entrance");
          $("#line1").html("Go into cave?");
          $("#btn1").html("Yes!!");

       }
       else{
          console.log("I am error");
       }
   };

 });
<p id = "line1"> You are in a field </p>
<button id = "btn1"> [ Go to cave ] </button>
AndrewL64
  • 15,794
  • 8
  • 47
  • 79