0

I'm working on a SVG file, and I'd like to count how many polygons have a certain class (lets say ".red")

Here's the simple javascript loop:

var polygons = document.getElementsByTagName("polygon");
var j = 0;
for (i = 0; i < polygons.length; i++) {
  if (polygons[i].className == "red") {
    j++;
  }
};

alert("There are " + j + " red shapes")

and the fiddle : https://jsfiddle.net/tuj0rmnx

I can't get the expected result. 0 is returned instead of 3... Can't figure out why... I guess there must be a DOM issue or someting, but can't get it right...

I have read this : How to access SVG elements with Javascript but I don't want to create an event. All I want to achieve at the end, is to "print" the result automatically in the page using document.write() method...

Any help appreciated!!

Community
  • 1
  • 1
Vinny
  • 233
  • 2
  • 13
  • 2
    Debugging 101: Add `console.log(polygons[i].className);` and look at the value you get. – Quentin Jan 04 '16 at 15:05
  • I'm having a hard time finding out the correct way to do this, but to my memory, SVG content is treated as a separate document from the HTML around it. You need to query for the SVG element itself, *somehow* get its "document", and then query inside of that. It's similar to how you'd inspect an iframe. – Katana314 Jan 04 '16 at 15:17
  • `document.querySelector('svg polygon')` is how you access inner svg elements. as in - "look in the svg document for a polygon." – Uzi Jan 04 '16 at 17:58

2 Answers2

2

You could just select the elements with the correct class in the first place:

var polygons = document.querySelectorAll("polygon.red");
alert("There are " + polygons.length + " red shapes")

Updated Fiddle


An alternative would be to use classList:

var polygons = document.getElementsByTagName("polygon");
var j = 0;
for (i = 0; i < polygons.length; i++) {
console.log( polygons[i].className );
  if (polygons[i].classList.contains( "red" ) )  {
    j++;
  }
};
alert("There are " + j + " red shapes")

Another Fiddle


Your code fails, because className does not return a string, but an SVGAnimatedString, which obviously is not equal to your "red".

Sirko
  • 72,589
  • 19
  • 149
  • 183
  • Hi Sirko, thanks a lot for your help! It does work fine in jsfiddle, but the problem I have now is "how do I access the elements inside a svg file". I use a CMS and scripts are separated from files. There must be an instruction to go and get the elements from my SVG file. Any idea? – Vinny Jan 04 '16 at 15:32
0

The properties in an SVG generally have different definitions than the same-named property might have in HTML.

The type of the property className is not a string. So you cannot compare it to a string constant like "red". It won't work.

The type of the property className in SVG is AnimatedString. AnimatedString has two properties:

  • baseVal which contains the initial value of the property, and
  • animVal which contains the current value of the property. Which can be different from baseVal if the property is currently being animated.

So for you code to work, you need to change your class test to:

if (polygons[i].className.baseVal == "red") {

See the demo below:

var polygons = document.getElementsByTagName("polygon");

var j = 0;
for (i = 0; i < polygons.length; i++) {
  if (polygons[i].className.baseVal == "red") {
    j++;
  }
};

alert("There are " + j + " red shapes")
.shapes {
  fill: #b9b9b9;
  fill-opacity: 1;
  stroke: white;
  stroke-opacity: 1;
  stroke-width: 0.002;
}

.red {
  fill: red
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="433" height="378" preserveAspectRatio="none" version="1.1" x="0" y="0">

  <g class="shapes">

    <polygon points="35.582,121.756 0.578,61.128 35.582,0.5 105.588,0.5 
 140.592,61.128 105.588,121.756 " />
    <polygon points="181.334,121.756 146.331,61.128 181.334,0.5 251.341,0.5 
 286.345,61.128 251.341,121.756 " />
    <polygon class="red" points="327.087,121.756 292.083,61.128 327.087,0.5 397.094,0.5 
 432.098,61.128 397.094,121.756 " />
    <polygon points="35.582,377.071 0.578,316.443 35.582,255.815 
 105.588,255.815 140.592,316.443 105.588,377.071 " />
    <polygon class="red" points="181.334,377.071 146.331,316.443 181.334,255.815 
 251.341,255.815 286.345,316.443 251.341,377.071 " />
    <polygon points="327.087,377.071 292.083,316.443 327.087,255.815 
 397.094,255.815 432.098,316.443 397.094,377.071 " />
    <polygon points="111.328,249.413 76.324,188.785 111.328,128.157 
 181.334,128.157 216.338,188.785 181.334,249.413 " />
    <polygon class="red" points="257.081,249.413 222.077,188.785 257.081,128.157 
 327.087,128.157 362.091,188.785 327.087,249.413 " />
  </g>
</svg>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • Hi Paul, thanks a lot for the explanation. It makes things much more clear to me. However, I'm facing a new problem now... how can I access to my SVG elements, knowing my SVG file is in , outside of the DOM. I'm not sure if I should ask a new post since it's a different issue... Regards – Vinny Jan 05 '16 at 16:05
  • That question has been answered already a number of times on SO. For example, see this quetsion: http://stackoverflow.com/questions/2753732/how-to-access-svg-elements-with-javascript – Paul LeBeau Jan 05 '16 at 17:29