'getElementsByClassName - Template inserted direct child can not be found under specific conditions

TLDR - See example HTML. First console.log call shows an empty resultset. I know how the fix this, but why does this happen? Chrome (101.0.4951.54) / Edge (101.0.1210.32)

I ran into the following issue: calling getElementsByClassName with a case sensitive name (inputStartState) on a container which has a direct child with said class name, the result is empty.

However: this only occurs when the element has been added using a template element AND an event listener has been attached to said element BEFORE inserting the template into the DOM.

This happens in Chrome (101.0.4951.54) and Edge (101.0.1210.32), but FireFox (100.0) is not affected.

Example:

<html>
<body>
  <div id="tester"></div>
  <template id="testTemplate">
    <div class="test"><input class="inputStartState"></div>
  </template>
  <script type="text/javascript">
    (function() {
      var container = document.getElementById("tester");
      container.innerHTML = "";
      var template = document.getElementById("testTemplate");
      var clone = template.content.cloneNode(true);
      var root = clone.firstElementChild;
// remove the line below line and it will work just fine - WHY?
      root.getElementsByClassName("inputStartState")[0].onblur = function() {   
        console.log("Blurrrrr");
      }
      container.append(clone);

      var el = document.getElementsByClassName("test")[0];
      console.log("Direct parent, with case: ",  el.getElementsByClassName("inputStartState"));
      console.log("Direct parent, lower case: ",el.getElementsByClassName("inputstartstate"));
        
      el = document.getElementById("tester");
      console.log("Parent's parent, with case: ",el.getElementsByClassName("inputStartState"));
      console.log("Parent's parent, lower case: ", el.getElementsByClassName("inputstartstate"));
})();
  </script>
</body>
</html>

Running this piece of script yields the following output to the console

Chrome (101.0.4951.54) / Edge (101.0.1210.32)
Direct parent, with case: HTMLCollection []
Direct parent, lower case: HTMLCollection [input.inputstartstate]
Parent's parent, with case: HTMLCollection [input.inputstartstate]
Parent's parent, lower case: HTMLCollection [input.inputstartstate]

The easy fix is to attach the event after inserting the template into the DOM. I'm more curious as to WHY doing it this way causes this weird, and very specific bug.



Solution 1:[1]

var testContainer = document.querySelector('#test'); var childNodeByClass = testContainer.querySelector('.my-class');

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Urvi Mistry