user3871
user3871

Reputation: 12718

JavaScript - extremely confused on removing elements from Container

I'm making a 2D, top-down Zelda style web rpg single player in JavaScript.

When the player (purple shirt) walks near a cat, it will "rescue" it... which basically removes the animalContainer from the ContainerOfAnimals (thereby removing animalContainer's BMP from the stage), and then add the id of that animalContainer to a rescuedTotal_Array...

The weird thing is, In the pic below, I'm able to rescue animalContainer2 and then rescue animalContainer1... But if I go from animalContainer1 to animalContainer2, it throws a

Uncaught TypeError: Cannot read property 'id' of undefined` error. 

... Basically:

Working way: get ID 22, then up to ID 21 ->>> One thing I notice with this is that the element name doesn't change for the ID... not sure why... so for the broken way... it may not be able to even associate element name animalContainer2 with an ID? But I don't know how the ID and the name could get disassociated like that..

ID in rescued array...: 22, element name: animalContainer1, rescued array length: 2, elem index pos: 0, index: 0

ID in rescued array...: 21, element name: animalContainer1, rescued array length: 2, elem index pos: 1, index: 0 

Broken way- throws error: get ID 21, then down to ID 22

ID in rescued array...: 21, element name: animalContainer1, rescued array length: 1, elem index pos: 0, index: 0 

1. Uncaught TypeError: Cannot read property 'id' of undefined 

enter image description here

Code Snippet:

        function grabIt(NPC_id, index) {
            //check if NPCid already exists in array before adding...
            if ($.inArray(ContainerOfAnimals.children[index].id, rescuedTotal_Array) == -1) {
                rescuedTotal_Array.push(ContainerOfAnimals.children[index].id);
            }
            if (rescuedTotal_Array.length == 2) {
                for (var z = 0; z < rescuedTotal_Array.length; z++) {
                    console.log("ID in rescued array...: " + rescuedTotal_Array[z] + ", \n element name: " + ContainerOfAnimals.children[index].name + ", rescued array length: " + rescuedTotal_Array.length + ",\n elem index pos: " + z + ",\n index: " + index);
                }
            }
            //when I remove the first added element to rescuedTotalArray... the 2nd element's index assumes first added element's index... (goes from 1 to 0)
            console.log(index);
            console.log("element removed: " + ContainerOfAnimals.children[index]);
            stage.update();
            ContainerOfAnimals.removeChild(ContainerOfAnimals.children[index]);
            updateHUD();
        }

I have no idea why the order in which I store elements in the array/remove them from the stage would matter...


EDIT: I feel I can solve this issue by removing element from ContainerOfAnimals by element ID instead of by index... by Container object offers no getChildID() function...

so I tried:

    var childToRemove = document.getElementById(ContainerOfAnimals.children[index]);
    console.log(childToRemove);
    ContainerOfAnimals.removeChild(childToRemove);

console.log(childToRemove) gives me null for children

But doing this: console.log(ContainerOfAnimals.children[index].id); gives me id 21, which is the correct id...

Upvotes: 1

Views: 1719

Answers (4)

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382160

Beware that EaselJS elements aren't DOM elements.

Supposing you want to remove an element by its id, I'd suggest this :

function removeElementById(container, id) {
   for (var i=container.getNumChildren(); i-->0;) {
       if (container.getChildAt(i).id===id) {
            container.removeChildAt(i);
            return true;
       }
   }
   return false;
}

But using the id might not be the best architectural solution. In my EaselJS program I keep a reference to the objects themselves so that I don't have to search them.

Upvotes: 1

user2539351
user2539351

Reputation: 19

I am not entirely sure whatever if this is the case (I can't know it without taking a look at your whole program), but it could be this:

I assume that your "ContainerOfAnimals" is a HTML element and that you are retrieving it's child nodes using it's .children -property. The thing is that .children -property returns a "live list"!

Let me demonstrate:

var children = ContainerOfAnimals.children;
console.log(children.length) // 2;

ContainerOfAnimals.removeChild(children[0]);
console.log(children.length) // 1;

Let's say that you remove the very first child of ContainerOfAnimals. What happens? The children -list has now changed so that the second element becomes the first element, third element becomes the second element etc...

You could fix this by using a static array containing all the children and like this:

var children = [].slice.call(ContainerOfAnimals.children);
console.log(children.length) // 2;

ContainerOfAnimals.removeChild(children[0]);
console.log(children.length) // 2;

Now removing the element from the DOM -tree does not remove the element from the children array (which is static). Remember, that [].slice.call does not work in IE8 or lower.

Let me know if this was the problem. I have not enough points to comment, so I had to make a full post :)

Upvotes: 1

some_coder
some_coder

Reputation: 340

It may be possible that your rescuedTotal_Array is an associative Array (or was morphed to one) and could contain something like:

rescuedTotal_Array = [1:object,2:object,object:object]

The array above has the length of 3. But you cannot access the third element via index 2, because its index is some kind of object.

Try to dump the content of your rescuedTotal_Array before accessing it (so you can see if everything is ok). This is not a solution, but it may help you so that you can find the error by yourself. Use something like

for (index in rescuedTotal_Array) {
    if (rescuedTotal_Array.hasOwnProperty(index)) {
        console.log(rescuedTotal_Array[index]);
    }
    else {
        console.log("no entry found for index: "+index);
    }
}

Upvotes: 1

Jan M.
Jan M.

Reputation: 127

HY,

Try for statement like this:

for(var z = rescuedTotal_Array.length; z >= 0; z-- )

If you noticed I just turned it around. It starts at the and going backwards. It is stupid but, maybe this error is just that :)

Let me know how it goes!

Regards

Upvotes: -1

Related Questions