javascript document.getElementsByClassName returns 0 for length

894359
894359 used Ask the Experts™
on
I have the below function:
    function _dtmIsAppDeclined(){
        var appDeclined = 0;
         //May have to move this into lower if statement 
        if((document.cookie.indexOf('startStandardOaoFlow=') !== -1)){
            s.events += (s.events == '') ? "event33" : ",event33";
        }
  
        var myCollection = document.getElementsByClassName('region-done-group');
        var i = myCollection.length;
        console.log("myCollection.length: " + i + " <---===> OAO4 myCollection holds: ",myCollection);
        while(i--) {
            if (myCollection[i].innerText.search('we cannot open the account') > -1) {
              console.log("5 ---===> OAO4 FOUND DECLINE TEXT");
            appDeclined = 1;
            s.events += (s.events == '') ? "event35" : ",event35";
            s.eVar23 ='decline';
            // Invoke marketing tags
            _dtmInsertStaticTags(sTags3);
            }
        }
        return appDeclined;
    };

Open in new window

The issue is that
var myCollection = document.getElementsByClassName('region-done-group');

Open in new window

Returns a length of 0 (see line 10 in the code) but still out puts the collection? I read that it is most likely because the getElementsByClassName returns a live collection. the length property of the object is 0 because at that point of time there is no element with that className in the DOM. ***Maybe 1 out 10 times when refreshing the page, the code works as expected*** How do I ensure that the classname is in the DOM before I do anything else? One caveat is this is a Single Page Application but it does have the ability for the user to refresh the page. This image shows the console log from line 10 above: Image showing console log for CollectionThanks!
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
David S.Consultant & Challenge Subduer
Top Expert 2009

Commented:
When are you calling your function?  It sounds like you need a DOMContentLoaded or load event listener.

Author

Commented:
The function is called either on page load (if user refreshes page) or when there is a pushstate change (Standard detection of the Single Page Application).  So my issue is I need to account for either situation in the same piece of code if possible? If I have to choose a single fix, it would be for the push state change but I'd like to address both situations.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Both should be catered for on a page load.

What invokes _dtmIsAppDeclined()?

When you say SPA - what framework / library are you using?
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
H Julian,
The app is made by a 3rd party so I'm not sure what framework it is made on? The _dtmAppDeclined() function is invoked within my code within a Direct Call rule injected via a Tag Management system (DTM). I did get this to work by delaying the code for 2 secs. before it runs but I'm assuming there is a much cleaner way to handle this?
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Are you placing your code inside a document ready block?

Author

Commented:
The code is invoked after the web app load on a specific route or when the page is reloaded on that specific route. It lives in a rule {piece of code} that loads when the web app loads but then sits there and waits for the specific route. The web app uses ajax to update the content or uses hidden divs etc.
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
That is not helping me.

I need to know if your JavaScript runs before the page is finished loading.

To illustrate
<html>
<head>
<script>
  var el = document.getElementsByClassName('.region-done-group');
  console.log(el.length);
</script>
</head>
<body>
<div class="region-done-group"></div>
</body>
</html>

Open in new window

Output 0

<html>
<head>
</head>
<body>
<div class="region-done-group"></div>
<script>
  var el = document.getElementsByClassName('.region-done-group');
  console.log(el.length);
</script>
</body>
</html>

Open in new window

Output 1
Or
<html>
<head>
<script>
  var el = document.getElementsByClassName('.region-done-group');
  console.log(el.length);
</script>
</head>
<body>
<div class="region-done-group"></div>
</body>
</html>

Open in new window

Output 0

<html>
<head>
<script>
  window.addEventListener('load', function() {
    var el = document.getElementsByClassName('.region-done-group');
    console.log(el.length);
  });
</script>
</head>
<body>
<div class="region-done-group"></div>
</body>
</html>

Open in new window

Output 1

If the call is reporting a length of 0 that is because when the code runs there are 0 elements on that page with that class - they have not been rendered yet.
This code needs to be run AFTER those elements have been rendered and you have not given me enough information to be able to determine how your code is operating.

Author

Commented:
I just had to delay the script when loaded. Since this script can be called at 2 different times (page refresh if on a specific route or once it hits this route in the SPA).
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Delaying the script is not a great solution - you want to rather find what event / condition fires to render the elements you are interested in and then fire your code for analysing those elements.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial