-2

Is there any way to detect the elements in proxy object that is returned from getElementsByTagName() ? I need to addEventListener to the returned svgs from below code

const svgs= document.getElementsByTagName('svg');
console.log('svgs',svgs);
const myArray = Array.from(svgs); 
console.log('myArray ',myArray); // This is returning [] 

Below is the log that i can see in console . Can some one help me to get the svgs=>target=>HTMLCollection(49) into array enter image description here

Gajini
  • 413
  • 1
  • 5
  • 21
  • https://jsbin.com/cayegesefi/1/edit?html,js,console — I can't reproduce the problem. Please provide a [mcve]. – Quentin Feb 28 '19 at 09:29
  • 2
    This looks like an asynchrony issue. The `svgs` object is a *live* collection, and your console is showing the content as it is at a later time (when you click to open the structure in the console), while the array reflects the state at the very moment of logging. – trincot Feb 28 '19 at 09:30
  • Possibly dupe: https://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays – Quentin Feb 28 '19 at 09:30

1 Answers1

1

The reason is that these svg elements are apparently added to the document asynchronously. By the time you look at the console and open the svgs structure, the svg elements have been loaded, but this was not the case yet at the moment your code ran and created the array. That you see them is because of the console's lazy loading.

If the svg elements are loaded on page load, then you might be lucky and you can just wrap your code in something like:

window.onload = () => { /* your code */ }

But it is more likely that this content is loaded via some Ajax calls, and then the above wont help.

You could listen to DOM mutation events:

const svgs = document.getElementsByTagName('svg');
console.log(svgs.length); // <-- presumably outputs 0

const listener = new MutationObserver(updated);
// This listens to changes under the BODY element. If you can be more 
// precise, then do so (to save resources). If you can do without
// the subtree option, then that is also preferred:
listener.observe(document.body, { childList: true, subtree: true });

function updated() {
    console.log(svgs.length); // <-- notice the increased length
    // Do whatever else you want to do with this collection.

    // If you are sure you have all you need, then stop the listener:
    listener.disconnect();
}

If the elements are populated all "at once", and you just want one call of the event listener, then you may still need to tune it with some debouncing pattern.

trincot
  • 317,000
  • 35
  • 244
  • 286