Search code examples
javascriptfor-loopsvgpathappendchild

Looping through elements is not working


I am trying to add an extra path to each SVG on a webpage. I set up my for loop and it is working, but once it loops through it tells me appendChild() is not a function. If I take everything out of the loop appendChild() works. What am I doing incorrectly here?

 var svg = document.getElementsByClassName('curve-position-bottom'); //Get svg element
 for (var i = 0; i < svg.length; i++) {
   console.log(svg.length);

   function addPath() {
     console.log('working');
     var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'path'); //Create a path in SVG's namespace
     newElement.setAttribute("d", "M0 0 C50 100 50 100 100 0  "); //Set path's data
     newElement.style.stroke = "#005780"; //stroke colour
     newElement.style.strokeWidth = "13px"; //Set stroke width
     newElement.style.fill = "none"; //Set stroke width
     svg.appendChild(newElement);
   }
   addPath();

 }
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 100 100" version="1.1" preserveAspectRatio="none" height="45px" class="engle-curve curve-position-bottom" style="fill:#e6e2af">
  <path stroke-width="0" d="M0 0 C50 100 50 100 100 0  L100 100 0 100"></path>
</svg>

<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 100 100" version="1.1" preserveAspectRatio="none" height="45px" class="engle-curve curve-position-bottom" style="fill:#e6e2af">
  <path stroke-width="0" d="M0 0 C50 100 50 100 100 0  L100 100 0 100"></path>
</svg>

<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 100 100" version="1.1" preserveAspectRatio="none" height="45px" class="engle-curve curve-position-bottom" style="fill:#e6e2af">
  <path stroke-width="0" d="M0 0 C50 100 50 100 100 0  L100 100 0 100"></path>
</svg>


Solution

  • The return value of document.getElementsByClassName is a NodeList, not an individual element. To use your defined SVG, you'll need to use svg[i].


    Also, unrelated to your question, but it would be a good idea to move that function definition out of the loop (for performance and scoping reasons) and to call it with an SVG element as a parameter. It would look more like this:

    var svg = document.getElementsByClassName('curve-position-bottom'); //Get svg elements
    
    function addPath(svg) {
        console.log('working');
        var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'path'); //Create a path in SVG's namespace
        newElement.setAttribute("d", "M0 0 C50 100 50 100 100 0  "); //Set path's data
        newElement.style.stroke = "#005780"; //stroke colour
        newElement.style.strokeWidth = "13px"; //Set stroke width
        newElement.style.fill = "none"; //Set stroke width
        svg.appendChild(newElement);
    }
    
    for (var i = 0, length = svg.length; i < length; i++) {
        addPath(svg[i]);
    }