I tried to remove a div inside the set timeout function but it give me the error in the title.
Here is the stack trace:
TypeError: Cannot read properties of undefined (reading '_elements')
at f.default.Element.remove (https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js:3:520693)
I’m currently in instance mode if you need to know
I could not make a MWE but my live code is right here
The code that is seemingly causing the issue is on line 438 with the code being this:
// Remove eveything if it is done loading
if ( FilesFullyLoaded || p.LoadPercent >= 100 ) {
FilesFullyLoaded = true; // Sets FilesFullyLoaded to true
p.LoadingText.html("Loading... DONE!!"); // Tells the user that the loading is done
p.noLoop(); // Stops the draw loop from looping
setTimeout(p.LoadingDiv.remove, 750); // <-- This line // Deletes div to make it disapere
}
else {
p.LoadingText.html(`Loading... ${p.round(p.LoadPercent)}%`) // Inform the user of the percentage of files loaded
}
I know this because every time I remove the line its fixed.
Oh, I thought it’d be that. But on a 2nd look I’ve spotted the obvious here:
For any function which depends on the keyword this (as methods normally do) we have to be watchful whether the object invoking it is the correct 1, b/c that becomes the this inside a function.
In the case of p.LoadingDiv.remove, remove()'s preceding property LoadingDiv contains the correct object which becomes the caller object when we manually invoke it like this: p.LoadingDiv.remove();
However, when we pass the expression p.LoadingDiv.remove to setTimeout() as its callback, it’s not LoadingDiv which is gonna invoke remove() anymore:
As an archaic workaround we could use method bind() in order to clone the method w/ a fixed this: setTimeout(p.LoadingDiv.remove.bind(LoadingDiv), 750);
But for modern JS, a wrapper function using the fat arrow expression syntax is the usual pick instead: setTimeout(() => p.LoadingDiv.remove(), 750);
P.S.: By JS (and Java) convention, regular variables, parameters & properties should use the lowerCamelCase style.
So property LoadingDiv is better off renamed as loadingDiv.