1

There are a bunch of span elements on the page that I'm trying to grab that are formatted like so:

<div class="ca-evp1 te" style="color:#2952A3">
    <span class="te-t">11am&nbsp;</span>
    <span class="te-s">Antoine Diel</span>
</div>

So, I decided to select them using getElementsByClassName() and then iterate over this HTMLCollection, which when I view in the developer console shows 32 items but when I check the length property it is 0.

  var toType = function(obj) {
    return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
  }
  var eventToClick = document.getElementsByClassName('te-s');
  console.log(eventToClick); // shows 32 elements
  console.log(toType(eventToClick)); //htmlcollection
  console.log(eventToClick.length); // 0...huh?

I must be missing something with how getElementsByClassName or HTMLCollections in general work, but I can't seem to figure it out through docs or Google at this point.

As far as I understand things, if I'm seeing all of those span elements as part of the console.log statement, they should be contributing to the length of the eventToClick HTMLCollection and I should be able to iterate over it with a for loop, but this does not work! Is the developer console performing some sort of witchcraft here, and I don't really have these elements as part of an HTMLCollection?

Here is a live version so you can replicate in your own browser: http://danielschroedermusic.com/apps/cal-test/cal.html

Posting a second image of the span elements in the console for one of the people helping out with this issue.

Working Solution, but not great!

document.addEventListener('DOMContentLoaded', function(event) {
  var intervalID = window.setInterval(myCallback, 50);
  function myCallback() {
    var eventToClick = document.getElementsByClassName('te-s');
    if (eventToClick.length > 0) {
      console.log(eventToClick);
      for (var i = 0; i < eventToClick.length; i++) {
        console.log(eventToClick[i]); // 32 elements!
      }
      clearInterval(intervalID);
    }
  }
});

As Harshal noted in the accepted answer, I was not able to grab the elements because my script was executing before they were loaded onto the page. The Google scripts which are loading this calendar data are really complex, and stepping through them with the debugger hasn't yielded a place where I can logically see the elements being added, so I tried using an interval timer to check for the presence of the elements with the class name I was looking for.

That seems to do the trick for now, I'm open to more graceful solutions if you have any! Still researching this...

enter image description here

enter image description here

djs
  • 3,947
  • 3
  • 14
  • 28
  • 1
    Needs more [mcve]. – melpomene Oct 03 '17 at 21:55
  • @melpomene just uploaded to live site, does that satisfy? – djs Oct 03 '17 at 21:59
  • When do these elements get added? `HTMLCollection` is a live collection. Meaning any elements added/removed from `document` will be reflected in that collection. So while the log showed length 0, by the time you expand the HTMLCollection in the console it has updated to contain new elements added to `document` – Patrick Evans Oct 03 '17 at 21:59
  • That looks horribly complicated. – melpomene Oct 03 '17 at 22:05
  • @melpomene I agree, this is just a silly side project to see if I can pull calendar info from an iCal embed and then reformat however I see fit. It seems like I should be able to get the HTMLCollection doing the method I've used though, that's what is stumping me. – djs Oct 03 '17 at 22:13

1 Answers1

3

You need to do document.getElementsByClassName('te-s') after the calendar is loaded.

The 32 you are seeing before is correct. It is showing you object of HTMLCollection which is reference to the array. So when the eventToClick is printed, it has zero values in it .. put a debugger and see it. But after the calendar is loaded the eventToClick is showing you all the values. The reason why the length is 0 is same. The length shown is pass-by-value. So when you requested it, the length was actually 0.

There must be some callback function after the calendar is loaded which you can use to get the correct value, you can get correct length over there.

enter image description here

If you need help in this let me know the calendar library you are using, would love to research on it.

Harshal Carpenter
  • 470
  • 1
  • 9
  • 24
  • That makes sense, I will dig around and see if this works and get back to you. – djs Oct 03 '17 at 22:20
  • @Daniel.Schroeder Let me know if you need help! ;) I like working with calendars – Harshal Carpenter Oct 03 '17 at 22:21
  • 1
    OK this was definitely the problem. I haven't figured out a graceful way of grabbing the elements after they are loaded because the Google scripts are doing all sorts of magic to the onload events and stepping through the debugger got me nowhere because of all the included scripts and crazy function calls. I was able to get a hold of the elements using setInterval and waiting until the call to getElementsByClassName returned some elements. For now, that is what I'm going with! – djs Oct 04 '17 at 03:40