0

I'm working on a clicker game in HTML, JS and CSS but when I go to do a for loop and set onclick, the onclick function only works for the last object. I'm using JSON data.

JS:

const Shop = document.getElementById("Shop")
const Upgrades = JSON.parse(json_upgrades)

let IncreasePerClick = function(Amount, ID) {
  console.log("Debug!", ID)
  let CurrentPerClick = Number(localStorage.getItem("PerClick") || 1)
  let CurrentBalance = Number(localStorage.getItem("Cheese") || 0)
  let Default = Number(document.getElementById(`Buy${ID}`).getAttribute("default"))
  let CostUp = Number(localStorage.getItem(`Buy${ID}CostUp`))
  let Cost = Number(localStorage.getItem(`Buy${ID}Cost`) || Default)

  console.log(Cost)
  if(CurrentBalance >= Cost){
    CurrentBalance -= Cost
    CurrentPerClick += Amount

    Cost += CostUp

    localStorage.setItem(`Buy${ID}CostUp`, CostUp)
    localStorage.setItem("Cheese", CurrentBalance)
    localStorage.setItem("PerClick", CurrentPerClick)
    localStorage.setItem(`Buy${ID}Cost`, Cost)
  }
}

for(let i = 0; i < Upgrades.length; i+=1){
  Shop.innerHTML += `<div class="UpgradeHolder">
    <span class="UpgradeName">${Upgrades[i]["name"]}</span>
    <button class="UpgradeButton" id="Buy${i}" amountup="${Upgrades[i]["amount"]}" default="${Upgrades[i]["default"]}" costup="${Upgrades[i]["costup"]}" itemtype="${Upgrades[i]["type"]}">Buy for ${Upgrades[i]["default"]}</button>
  </div>
  `
  console.log("Added div!")

  let NewUpgradeButton = document.getElementById(`Buy${i}`)
  let UpgradeType = NewUpgradeButton.getAttribute("itemtype")

  let CostUp = Number(NewUpgradeButton.getAttribute("costup"))

  let Default = Number(NewUpgradeButton.getAttribute("Default"))
  let AmountUp = Number(NewUpgradeButton.getAttribute("amountup"))

  if(UpgradeType == "ClickUpgrade"){
    NewUpgradeButton.onclick = function(){
      IncreasePerClick(AmountUp, i)
      UpdateBalance()
    }
    console.log("Set Onclick!", i, AmountUp)
  }
}

JSON (in js file):

const json_upgrades = `[
  {"name": "Clickbot", "default": 50, "type": "ClickUpgrade", "amount": 1, "costup": 10},
  {"name": "Click Machine", "default": 125, "type": "ClickUpgrade", "amount": 3, "costup": 15}
]`

When I click on any button other than the last one it doesn't do anything, how can I fix this? I can provide screenshots.

Screenshot in this screenshot it shows the 2 buttons, on the right the console says "Debug! 1", 1 being the ID of the 2nd button. That is said as a result of pressing the 2nd button.

When I press the first button, it does nothing.

Edit: I got it to work after trying a few different things!

Community
  • 1
  • 1

2 Answers2

0

Here is a full example of your code working with the changes I will comment below: https://jsbin.com/hezubuhali/edit?html,js,console,output (to see it working you need to click in the button "Run with JS" on the right side of your window, in the last panel).

Assignments to innerHTML causes the loss of the event listeners. You need to use DOM functions. You can find additional examples here.

You also should not use i at IncreasePerClick(AmountUp, i) in your onclick event. The value of i will be the last value for all the buttons when you make your code works. I proposed a quick solution below for you to see it working.

In summary:

  • I replaced innerHTML with appendChild. I am using a template element to convert your code to DOM elements (you can see a full explanation here)
  • I am using this instead of i inside the onclick event to get your button ID.
saulotoledo
  • 1,737
  • 3
  • 19
  • 36
0

When you += the innerHTML the current applied events get erased, because the innerHTML gets rewritten. There are several ways to get around this. The one below is applying the events to Shop, which is not getting rewritten, so the event stays. Another way for example would be to run the loop twice and apply all the events after the innerHTML has been written.

const Shop = document.getElementById("Shop")
const json_upgrades = '[{"name": "Clickbot", "default": 50, "type": "ClickUpgrade", "amount": 1, "costup": 10},{"name": "Click Machine", "default": 125, "type": "ClickUpgrade", "amount": 3, "costup": 15}]';
const Upgrades = JSON.parse(json_upgrades)

let IncreasePerClick = function(Amount, ID) {
  console.log(`click ${ID}`);
}

for(let i = 0; i < Upgrades.length; i+=1) {
  Shop.innerHTML += `<div class="UpgradeHolder">
    <span class="UpgradeName">${Upgrades[i]["name"]}</span>
    <button class="UpgradeButton" id="Buy${i}" amountup="${Upgrades[i]["amount"]}" default="${Upgrades[i]["default"]}" costup="${Upgrades[i]["costup"]}" itemtype="${Upgrades[i]["type"]}">Buy for ${Upgrades[i]["default"]}</button>
  </div>`;

  let NewUpgradeButton = document.getElementById(`Buy${i}`);
  let UpgradeType = NewUpgradeButton.getAttribute("itemtype");

  let CostUp = Number(NewUpgradeButton.getAttribute("costup"));

  let Default = Number(NewUpgradeButton.getAttribute("Default"));
  let AmountUp = Number(NewUpgradeButton.getAttribute("amountup"));

  if(UpgradeType == "ClickUpgrade") {
    Shop.addEventListener('click', function(e, t) {
      if(e.toElement.id != NewUpgradeButton.id) return;
      IncreasePerClick(AmountUp, i);
      // UpdateBalance();
    });
  }
}
<div id="Shop"></div>
SirPilan
  • 4,649
  • 2
  • 13
  • 26