1

I have SVG elements (g, path, polygon) with unique IDs for each, but they share the same class.

<svg>
  <!-- 1002027 -->
  <polygon id="_1002027" data-name="1002027" class="site" points="1708.49 1009.6 1719.01 1018.1 1752.71 1014.51 1761.21 1003.99 1757.63 970.29 1747.1 961.79 1713.41 965.37 1704.9 975.9 1708.49 1009.6"/>
  <!-- 1002028 -->
  <polygon id="_1002028" data-name="1002028" class="site" points="1708.49 1009.6 1719.01 1018.1 1752.71 1014.51 1761.21 1003.99 1757.63 970.29 1747.1 961.79 1713.41 965.37 1704.9 975.9 1708.49 1009.6"/>
  <!-- ... -->
</svg>

Then I want the corresponding div to be displayed if the element is clicked, and to be hidden if the user clicks outside the element.

<div id="content_1002027" class="svgcontent"">Text Here</div>
<!-- and -->
<div id="content_1002028" class="svgcontent"">Text Here</div>
<!-- ... -->

Now I can achieve this by this script:

// Show 1002027
document.getElementById('_1002027').addEventListener('click', function (event) {
  document.getElementById("content_1002027").style.display = "block";
}, false);

// Show 1002028
document.getElementById('_1002028').addEventListener('click', function (event) {
  document.getElementById("content_1002028").style.display = "block";
}, false);

document.addEventListener('click', function clickOutside(event) {
  // Hide 1002027
  if (!document.getElementById('_1002027').contains(event.target)) {
    document.getElementById("content_1002027").style.display = 'none';
  }
  // Hide 1002028
  if (!document.getElementById('_1002028').contains(event.target)) {
    document.getElementById("content_1002028").style.display = 'none';
  }
});

However, with this method, I have to repeat this script for each id. If I had 60 of the elements, there would be a lot of code.

How can I achieve this for all id by writing just once?

rozsazoltan
  • 2,831
  • 2
  • 7
  • 20

1 Answers1

2

Solution

Retrieve all elements of this class type where, by iterating through each one with a loop, you can apply the onclick operation to each.

const siteElements = document.querySelectorAll('svg > .site');

// Add click event listener to all '.site' elements
siteElements.forEach((element) => {
  element.addEventListener('click', function (event) {
    // Show content for this element
    document.getElementById(`content_${this.getAttribute('data-name')}`).style.display = 'block';
    
    // Hide all content except the current one
    siteElements.forEach(site => {
      if (site !== this) {
        document.getElementById(`content_${site.getAttribute('data-name')}`).style.display = 'none';
      }
    });
  }, false);
})

// Add click event listener to the document (detect clicks outside)
document.addEventListener('click', function clickOutside(event) {
  // If the clicked element is not a '.site' element
  const clickedOnSite = Array.from(siteElements).some(site => site.contains(event.target));
  if (!clickedOnSite) {
    // Hide all content
    document.querySelectorAll('.svgcontent').forEach(content => {
      content.style.display = 'none';
    });
  }
});
.svgcontent {
  display: none;
}
<!-- 1. -->
<div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080">
    <polygon id="_1002027" data-name="1002027" class="site" points="1708.49 1009.6 1719.01 1018.1 1752.71 1014.51 1761.21 1003.99 1757.63 970.29 1747.1 961.79 1713.41 965.37 1704.9 975.9 1708.49 1009.6" />
  </svg>
  <div id="content_1002027" class="svgcontent">Text Here</div>
</div>
<!-- 2. -->
<div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080">
    <polygon id="_1002028" data-name="1002028" class="site" points="1708.49 1009.6 1719.01 1018.1 1752.71 1014.51 1761.21 1003.99 1757.63 970.29 1747.1 961.79 1713.41 965.37 1704.9 975.9 1708.49 1009.6" />
  </svg>
  <div id="content_1002028" class="svgcontent">Text Here</div>
</div>
<!-- ... -->

More information

rozsazoltan
  • 2,831
  • 2
  • 7
  • 20
  • There is still an issue. When I clicked on the other .site element, the new content appeared while the previous one remained visible. To clear all of the content, I have to click on the empty area. Maybe because they're all within a single element. How can I fix this? – nitinatsangsit Aug 20 '23 at 08:16
  • In this case, you didn't exactly use my code. The "Run code snippet" can be used to test that clicking on another SVG makes the other "content" disappear. In my code, I handled this in the onclick event. If you click on an element, I know which one you clicked on, and I hide all the others. **You can find this script under the comment "Hide all content except the current one."** – rozsazoltan Aug 20 '23 at 08:24
  • It is important that every polygon, g, path, etc. have a separate data-name (and I found it more reasonable to locate the content element based on the data-name). – rozsazoltan Aug 20 '23 at 08:25
  • 1
    Ok, I've got it. Some content div are missing. It would work if all of them existed. Thanks. – nitinatsangsit Aug 20 '23 at 09:17