Summary: Is there a way to get a list of the elements currently observed by a given ResizeObserver?
Assume an existing ResizeObserver that observes some elements
let observer = new ResizeObserver(_ => _.forEach(_ => console.log(_.contentBoxSize[0])));
observer.observe(document.getElementById('my-element-1');
observer.observe(document.getElementById('my-element-2');
Is there a way to get the elements the ResizeObserver is observing like
observer.getObservedElements() === [ // this API does not exist
document.getElementById('my-element-1'),
document.getElementById('my-element-2')
];
Use cases that I would have used such an API (there are probably more):
Am I missing something from the MDN docs or the CSSWG draft? I only see observe(), unobserve() and disconnect().
The problem with such an API is that it would keep the observed elements from being Garbage Collectable, even though the specs are still not clear on this case, implementations (at least Chrome) do currently unobserve target Elements that aren't referenced anywhere else. If they had to expose which elements are being observed, they would need to keep it in the list with the potential memory leak that follows.
Though for your own testing case, you could probably overwrite the observe and unobserve methods to update a Set attached to the Observer:
(function() {
const targets = new WeakMap();
Object.defineProperty( ResizeObserver.prototype, "targets", {
get() {
let slot = targets[ this ];
if( !slot ) {
slot = new Set()
targets[ this ] = slot;
}
return slot;
}
} );
const original_observe = ResizeObserver.prototype.observe;
const original_unobserve = ResizeObserver.prototype.unobserve;
ResizeObserver.prototype.observe = function( elem, ...args ) {
this.targets.add( elem );
return original_observe.call( this, elem, ...args );
};
ResizeObserver.prototype.unobserve = function( elem, ...args ) {
this.targets.delete( elem );
return original_observe.call( this, elem, ...args );
};
})();
const observer = new ResizeObserver( (entries) => console.log( "size changed" ) );
observer.observe( document.getElementById( "target1") );
observer.observe( document.getElementById( "target2") );
observer.unobserve( document.getElementById( "target1") );
console.log( [...observer.targets] ); // #target2
[id^="target"] { border: 1px solid; height: calc(50% - 4px); }
.resizeable-container {
width: 50vw;
height: 50vh;
resize: both;
overflow: auto;
}
<div class="resizeable-container">
<div id="target1"></div>
<div id="target2"></div>
</div>
Also, regarding your first use-case, you don't have to worry about observing multiple times the same Element, it's already handled in the specs: if you call observe with an Element that is already in the observer's [[observationTargets]] internal slot, it will first get removed and then re-added with the new options if any.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With