0

I'm making a point and click adventure/dating sim like website. I am currently making Dialogue Options. Options that come up at a certain point in conversation that allows the user to select their response, or chose some sort of prompt option.

My entire system seems to work fine except one step where I'm populating the Dialogue Options onto the prompt.

//Run through up to 10 dialogue options and add to dialogue option window.
    for(var i = 1; i<3; i++)
    {           
        var Option = eval(O['o'+i]);
        if(typeof(Option) !== 'undefined')
        {
            $("#CAM_OptionsFrame").append("<p id='DialogueO"+i+"' class='clickable'>"+Option[0]+"</p>");

            var funcString = Option[1];
            var func = window[funcString];
            $('#DialogueO'+i).on("click",function() {
                $( this ).off("click");
                endDialogueOption(time, O.noHide, function(){func();});
            });
        }
    }

I load any number of Dialogue Options and their partner functions from an argument. Then loop through them listing the name in the HTML of the prompt and giving them a unique ID.

Then I select the element by the unique ID and give it an onclick listener which refers to the function passed in by the specific option.

However, ALL the elements run the last options function when you click them. I suspect the listener points to the "func" variable and updates every time I change it in the loop.

How do I make the listener refer to the instance of the variable so that every new listener I make refers to it's own "func" variable?

1 Answers1

1

This is a classic closure issue. You have 2 options, once is invoke each function with the current index of the loop.

for (var i = 1; i < 3; i++) {
  (function(index) {
    var Option = eval(O['o' + index]);
    if (typeof(Option) !== 'undefined') {
      $("#CAM_OptionsFrame").append("<p id='DialogueO" + index + "' class='clickable'>" + Option[0] + "</p>");

      var funcString = Option[1];
      var func = window[funcString];
      $('#DialogueO' + index).on("click", function() {
        $(this).off("click");
        endDialogueOption(time, O.noHide, function() {
          func();
        });
      });
    }
  })(i)
}

If you have ES6 support in the code base, then the only thing you need to change, if var to let in the for loop.

for (let i = 1; i < 3; i++) {
.. everything else remains the same.
Sushanth --
  • 55,259
  • 9
  • 66
  • 105
  • When you say: "If you have ES6 support in the code base" Is there a particular installation process I need to do or can I assume that my browser, webhost has everything necessary to run it natively? – Gaian Swine Helmers Jun 22 '17 at 22:24
  • 1
    Generally you would have `babel` or `Traceur` to transpile your ES6 code to ES5 ( the current implementation of JS in your browsers ). By the time the browsers implement it, would be a while. – Sushanth -- Jun 22 '17 at 22:26
  • Thanks for the info! I'll be using your other fix for now. I don't have the energy to learn another library right now. It's good to know though. – Gaian Swine Helmers Jun 22 '17 at 22:47