I want to create a WeakSet
of all elements that are not 100% contained within the css layout bounds of the document root (<html>
tag). I need it to update in real time and not have a huge hit on browser performance.
To achieve this I used the intersectionObserver API as follows below and this creates my WeakSet with all the elements I expect when I pass it document.querySelectorAll('body *')
My problem is that when I want to test if an element is in my WeakSet, I get the correct answer in Safari. However, both Chrome and FireFox always return false
when I check a matching element using overflowedElements.has(el)
This appears to be due to Chrome/FireFox incorrectly creating a separate reference to the element via the IntersectionObserverEntry: target property, which then leads to there being two non-matching references to the same element.
Therefore I guess my question is how can I cheaply get the correct element references into my WeakSet, so I can match them in all browsers?
const options = {
root: document.documentElement,
rootMargin: '0px',
threshold: 1,
}
const overflowedElements = new WeakSet()
const callback = (entries) => {
entries.forEach((entry) => {
if (entry.intersectionRatio !== 1) {
overflowedElements.add(entry.target)
} else {
overflowedElements.delete(entry.target)
}
})
console.log('overflowedElements', overflowedElements)
}
const observer = new IntersectionObserver(callback, options)
export const observeOverflow = (nodeList) => {
nodeList.forEach((el) => {
observer.observe(el)
})
}
export const isOverflowed = (el) => overflowedElements.has(el)
In case anyone else ever needs to do this, the workaround was to use entry.target.toggleAttribute
and then document.querySelectorAll
to create a nodeList
rather than a weakSet
. Which in my case turned out to be more useful and better performing.