33
  var eval_table = document.getElementsByClassName("evaluation_table");
  console.log(eval_table);

This displays as:

[item: function, namedItem: function]0: 
    table.widefat.fixed.evaluation_table
    length: 1
    __proto__: HTMLCollection

However, when I try to get a length of eval_table, eval_table.length, it returns a value of 0. I've used this approach before, had no issues with this approach before. Is there anything wrong with what I'm trying to achieve above?

Jack hardcastle
  • 2,748
  • 4
  • 22
  • 40
  • 3
    [Works fine](http://fiddle.jshell.net/Pisi2012/7hc3qrhu/). Perhapes, a typo in your code? – alexP May 13 '15 at 10:07
  • Nope, no typo, perhaps my environment, working in wordpress, although this shouldn't affect vanilla javascript? @alexP – Jack hardcastle May 13 '15 at 10:08
  • 1
    maybe your js is executed before the elements are created? –  May 13 '15 at 10:10
  • No, it shouldn't. Are the elements already in the DOM when you're calling the function? – alexP May 13 '15 at 10:10
  • yeah, @alexP, if I console.log the collection itself it can see that they're there, it sees the length of them (seen in the above code snippet), however when I try to directly reference the length of these, returns 0. – Jack hardcastle May 13 '15 at 10:11
  • 1
    See this example: http://fiddle.jshell.net/7hc3qrhu/3/ - the code has been moved to `head`, so it executes before the elements are in the DOM (logs an empty array and `0` for length), but once you expand the collection in console the elements show up, because it shows the state of the object at the moment of expasion, and it is a live collection. – pawel May 13 '15 at 10:21
  • it's working in jsbin with a simple table http://jsbin.com/rupobicibi/1/` , can you post more code , HTML may be – bmscomp May 13 '15 at 10:22

3 Answers3

65

This is because your JS is running before the elements are rendered to the DOM. I bet the script you have running is loaded before the <body> of your html. You have two options:

  1. Add the self-executing <script> as the last thing in your <body> tag or;
  2. Wrap your function so that it waits for the DOM to be loaded before executing. You can do this with either:
    • jQuery's $(document).ready or
    • if you're not running jQuery: document.addEventListener("DOMContentLoaded", function(e) {// do stuff })

Code sample below:

<html>
  <head></head>
  <script>
    document.addEventListener("DOMContentLoaded", function(e) {
      var eval_table = document.getElementsByClassName('evaluation_table');
      console.log(eval_table, eval_table.length);
    });
  </script>
  <body>
    <div class="evaluation_table"></div>
    <div class="evaluation_table"></div>
    <div class="evaluation_table"></div>
    <div class="evaluation_table"></div>
  </body>
</html>
blankmaker
  • 681
  • 5
  • 6
  • 4
    Thank you so much. You made my day. I would have accepted this answer. – Amin Mohamed Ajani Jun 16 '16 at 11:10
  • 2
    Well now I feel like a moron. Tried so many different solutions and it turned out they would probably have all worked, and I just needed to wait for the document to be ready! Doh! – Olly John Jan 16 '18 at 07:34
  • @blankmaker Thanks for this answer. Can you please have a look, this one is related to above question -> https://stackoverflow.com/questions/60601380/html-collection-length-is-0-even-after-dom-has-been-rendered – Shantanu Tomar Mar 09 '20 at 13:16
  • 3
    @blankmaker This still didn't help me, I'm still getting length 0 whereas a I can see 3 elements in it. – DLV Jul 14 '21 at 04:39
  • THANK YOU I've been searching for hours for this – sophiemachin Feb 24 '22 at 20:10
3

In order to access the element at position 0 of HTMLCollection you should use

        setTimeout(() => {
          let elms = document.getElementsByClassName('ClassName').item(0)
        }, 0);

Using setTimeout to make sure DOM is finished render.

giapnh
  • 2,950
  • 24
  • 20
1

You could write the code inside the

$('document').ready(function(){
         // your code
   });

or on body onload or on DOM ready

<body>
Your HTML here

<script>
// self executing function here
(function() {
    var eval_table = document.getElementsByClassName("evaluation_table");
    console.log(eval_table,eval_table.length);
})();
</script>
</body>

I have tried in this jsFiddle

sachin.ph
  • 1,078
  • 12
  • 24