I have a mutation observer set up – it’s meant to track changes in the amount of elements added to a div “box” on the page, and if there are too many visible elements added (more than 6), it’s supposed to add page navigation buttons which would allow to switch between page 2 (elements beyond the 6th one) and back to page one (which shows first 6 elements).
This is achieved by first setting up this “storage” object outside of the mutation observer:
storedNodes = {
nodesToStay: {
},
nodesToMove: {
}
}
Then I make an array by using querySelectorAll on all nodes within this box that fit the “visible” requirement like this: const elementsToStay = Array.from(textField.querySelectorAll(":scope > div:not(.gone)"))
and get their IDs with this mapping method: idOfStayingElements = elementsToStay.map(node => node.id)
After that, I sort my nodes like this:
if (elementsToStay.length > 0) {
for (let i = 0; i < Math.min(6, elementsToStay.length); i++) {
storedNodes["nodesToStay"][elementsToStay[i].id] = elementsToStay[i];
}
}
if (elementsToStay.length > 6) {
const elementsToMove = elementsToStay.slice(6);
idOfMovedElements = elementsToMove.map(node => node.id);
for (let i = 0; i < elementsToMove.length; i++) {
storedNodes["nodesToMove"][elementsToMove[i].id] = elementsToMove[i];
document.getElementById(idOfMovedElements[i])?.remove();
delete storedNodes["nodesToStay"][elementsToMove[i].id];
}
}
Once the amount of keys in the storedNodes[“nodesToMove”] gets to 1 or more, I add page navigation with event listeners.
If “page 2” or “page 1” button is clicked, I use the replaceChildren() on the box holding elements to remove all previously present nodes.
Page 1 button is only supposed to be visible if we’re viewing the second ‘page’ (to allow us to go back to ‘staying’ elements), and Page 2 button is only supposed to be visible if we’re on first ‘page’.
When page 1 is clicked, this happens:
pageOne.classList.add("invisible");
pageTwo.classList.remove("invisible");
for (let id of idOfStayingElements) {
if (storedNodes["nodesToStay"][id]) {
textField.appendChild(storedNodes["nodesToStay"][id]);
}
}
When page 2 is clicked, this happens:
pageOne.classList.remove("invisible");
pageTwo.classList.add("invisible");
for (let id of idOfMovedElements) {
if (storedNodes["nodesToMove"][id]) {
textField.appendChild(storedNodes["nodesToMove"][id]);
}
}
Invisible class sets opacity to 0 and visibility to hidden.
The problem is, page 1 event listener doesn’t actually do anything, even though page 2 button works as intended.
As I’ve tested this further, I see that the issue lies specifically in this line: elementsToStay = Array.from(textField.querySelectorAll(":scope > div:not(.gone)"))
As once we get to the next page, all child elements of textField get removed, and we’re only left with elements that were previously stored within elementsToMove… so that becomes the new contents of elementsToStay
I’ve tried to fix this logic by instead making an “allElements” array where format the above-mentioned nodeList, and then tried to extract 1 to 6 elements from allElements to our elementsToStay, but that didn’t fix this behavior as it’s doing the same thing that we were doing before, but in more steps.
At the moment I just need to figure out proper logic for “remembering” what was on the first page, but I’m a bit lost for how I can achieve that at this point.
Here’s the relevant bit of code: https://jsfiddle.net/nj6zk5de/
Here’s the code in bigger scheme of things (starts from line 1477): https://github.com/pilzpuffer/etch-a-sketch/blob/main/script.js