1

I am attempting to find elements that have a certain class and make an array of their IDs.

var youtubeVids = document.getElementsByClassName('youtube');
var ytVidIds = [];
for(i = 0; i < youtubeVids.length; i++) {
    ytVidIds[i] = jQuery(youtubeVids[i]).attr('id');
}

I can see the correct array of elements in the console if I use:

console.log( youtubeVids );

However, I get a value of '0' when I use:

console.log( youtubeVids.length );

This tiny little bug is destroying the functionality of my entire site! Please offer some wisdom if you can see what I'm doing wrong.

edit: Heres the HTML

<div class='youtube' id='slide_0'></div>
<div id='slide_1'></div>
<div id='slide_2'></div>
  • can you update us with what you get from `console.log(youtubeVids)` – Ahmed Can Unbay Sep 06 '17 at 17:03
  • do you see property `length` when you do `console.log( youtubeVids );`? – curveball Sep 06 '17 at 17:03
  • HTMLCollection(1) length:1 – CandyPaintedRIMS Sep 06 '17 at 17:05
  • [I can't reproduce that error](https://jsfiddle.net/33cf5ubh/2/). – Andy Sep 06 '17 at 17:06
  • can you please share the html? – brk Sep 06 '17 at 17:06
  • Uh, why not `var ytVidIds = $('.youtube').map( x => x.id).get()` – adeneo Sep 06 '17 at 17:06
  • @curveball yes i do – CandyPaintedRIMS Sep 06 '17 at 17:06
  • 1
    Would these elements by any chance be inserted dynamically, for instance from some script that inserts videoes, or are they present in the HTML from the start. – adeneo Sep 06 '17 at 17:07
  • I guess all are in agreement that the link is needed. Generally it should work. So, it seems something weird is going on out there. – curveball Sep 06 '17 at 17:08
  • Adding to adeneo's comment, if they're not is your JS at the bottom of the page/wrapped in a `ready` function so that you're waiting for the DOM to load before you interrogate it? – Andy Sep 06 '17 at 17:08
  • here's the link: [link](http://getonlinenola.faudostaging.com/fsd/) – CandyPaintedRIMS Sep 06 '17 at 17:17
  • I suspect the reason that `console.log( youtubeVids )` works and `console.log( youtubeVids.length )` does not is due to [Chrome's `console.log()` lazy evaluation quirk](https://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays), since [`document.getElementsByClassName()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName) provides a live collection of elements, and is later updated due to [dynamic insertion](https://stackoverflow.com/questions/46080715/unable-to-use-length-with-a-nodelist#comment79123206_46080715). – Patrick Roberts Sep 06 '17 at 17:21
  • maybe good old `Array.prototype.slice.call(youtubeVids)` will help to get away from that live-collection? – curveball Sep 06 '17 at 17:28
  • I just tried Array.prototype.slice.call(youtubeVids) and it's ineffective. In the console, using Array.prototype.slice.call(youtubeVids) just gives me an empty array. – CandyPaintedRIMS Sep 06 '17 at 17:34
  • not in the console - see my answer. Change the script itself. – curveball Sep 06 '17 at 17:36

1 Answers1

1

well, try the following:

var youtubeVids = Array.prototype.slice.call(document.getElementsByClassName('youtube'));

In case your live collection eventually gets altered, the real array is always there for you.

curveball
  • 4,320
  • 15
  • 39
  • 49
  • This does help highlight the issue, but based on @CandyPaintedRIMS, does not resolve it. As was pointed out, since the elements are inserted dynamically, this will just return an empty array since the script executes this query before the elements are actually inserted. The real answer is to execute the query after the elements have been dynamically inserted. – Patrick Roberts Sep 06 '17 at 17:41
  • sorry :) Lets wait the feedback from the OP. – curveball Sep 06 '17 at 17:45
  • there is no dynamic insertion at least in the video-slideshow.js file - http://getonlinenola.faudostaging.com/wp-content/plugins/gon-video-slideshow/js/video-slideshow.js As for the rest of his scripts - who knows :) Besides, it has 1 `.youtube` video in the final markup and array of size 1 is visible in the console when he outputs `Array.prototype.slice.call(document.getElementsByClassName('youtube'))` and it seems it has always been there... – curveball Sep 06 '17 at 17:52
  • for whatever reason, this solution was able to return the array that I was looking for. Thank you @curveball – CandyPaintedRIMS Sep 06 '17 at 17:54
  • @CandyPaintedRIMS if this answered your question, please mark it as the [accepted answer](https://stackoverflow.com/help/accepted-answer) – Patrick Roberts Sep 06 '17 at 17:56
  • Nice to hear! But anyway check what happens with your `.youtube` elements. Maybe some other script takes some actions you don't properly control yet. – curveball Sep 06 '17 at 17:58