2

I'm coding a browser RPG game in JavaScript and I would like to create an inventory.

For each item added I want some buttons for equip item, drink a potion etc but I can't get the Object of the item selected on the list of my div #inventory

    <!DOCTYPE html>
<html>

<body>
<div id="inventory"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<script type="text/javascript">

var inventory = {
    potion : [],
    weapon: [],
}

class Item {
 
    constructor(name) {
        this.element       = document.createElement('div');
        this.name          = name;
        this.btnUse        = document.createElement('button');
        this.btnDelete     = document.createElement('button');
        this.btnEquip      = document.createElement('button');
        return this;
    }
  
    delete() {
        this.element.remove();
        const itemType = Object.getPrototypeOf(this).constructor.name.toLowerCase();
        inventory[itemType].splice(inventory[itemType].indexOf(this), 1);
    }

    addInventaire() {
        document.querySelector("#inventory").appendChild(this.element);
        const itemType = Object.getPrototypeOf(this).constructor.name.toLowerCase();
        inventory[itemType].push(this);

        let boirePotion = this.btnUse;
        boirePotion.setAttribute("class", "boirePotion");
        boirePotion.innerHTML = "drink potion";
        document.querySelector("#inventory").appendChild(boirePotion)

        let supprimer = this.btnDelete;
        supprimer.setAttribute("class", "supprimer")
        supprimer.innerHTML  = "delete";
        document.querySelector("#inventory").appendChild(supprimer);
    }
}
  
class Potion extends Item {
  
    constructor(name, value) {
        super(name);
        this.value             = value;
        this.element.innerText = this.description;
        return this;
    }

    get description() {
        return this.name + ' : ' + this.value;
    }
  
}

var healPotion    = new Potion("heal potion", 10);
var healPotionOne = new Potion("heal potion 1", 10);
var healPotionTwo = new Potion("heal potion 2", 10);

healPotion.addInventaire();
healPotionOne.addInventaire();
healPotionTwo.addInventaire();

</script>
</body>
</html>

2

1 Answer 1

1

According to my understanding your problem is that some items do not respond to events that you would expect to be handled, probably by the code below:

equiper.addEventListener("click", function() {
  // that here i block, i want whene i click on this button 
  // the object of the item and not the div element
  // to do something like this : 
  inventaire.itemType[indexItem].equiperObjet();
});

The problem seems to be that you run .addEventListener()

  1. on an array-like-object, not on its elements
  2. before the items are added. So the items created after the code above

Fix:

function initiallizeEquipersEvent() {
let equipers = document.querySelector(".equiper:not(.initialized)");
  for (let indexItem in equipers) {
    equipers[indexItem].addEventListener("click", function() {
      // that here i block, i want whene i click on this button 
      // the object of the item and not the div element
      // to do something like this : 
      inventaire.itemType[indexItem].equiperObjet();
    });
    equipers[indexItem].className += " initialized";
  }
}

You will need to call this function above when you intend to initialize the events. See that we only load the items which are not initialized yet to avoid duplicating the events and we loop the results.

Sign up to request clarification or add additional context in comments.

3 Comments

@nicolasmontmayeur the convention I have chosen was that whenever an item having an equiper class has the initialized class as well, then any calls to initiallizeEquipersEvent will ignore it, to avoid defining the same event many times, because that would result in the execution of the event function many times and that could cause problems. In the line you have mentioned, I refer to the current equiper in the loop, identified by indexItem and write " initialized" ad the end of its class name. This way that item will have the initialized class from now on, see the start of this comment.
but "indexItem" is the index of the button on the div and isn't the same than the index of my item on my var inventory
@nicolasmontmayeur I see. According to your current structure you could use parseInt(indexItem / 2) to get the index of your item on your inventory by the button index. However, that would assume that you will always have two buttons. It is much better to wrap a div around your items and provide a class for it. Then you could loop the item divs and use an inner loop to loop their buttons.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.