Home > OS >  Can SVG elements be tagged for later retrieval?
Can SVG elements be tagged for later retrieval?

Time:05-10

I have many dynamically generated SVGs inside my HTML document. They contain (among other elements) some <text> elements, sort of like this:

<svg>
    // bunch of other elements
    <text x="50" y="25" text-anchor="middle" dominant-baseline="central" >info 1</text>
    <text x="50" y="75" text-anchor="middle" dominant-baseline="central" >info 2</text>
    // more other elements
</svg>

Is there anything like an id or name attribute that I can use for these two pieces of text, so that I can dynamically change them later? id is supposed to be unique in the whole document, and I have many of these SVGs. name appears to mean something different in SVG (as opposed to HTML forms), and in any case might be deprecated. I'm hesitant to use class, since this really isn't about styling and I don't want weird conflicts with other styles that might be present in the document. (I don't have control over the document my code is used in, or its stylesheets.) I also don't want to have to search the whole document for the element I'm looking for, since I'll already have a pointer to its parent. Ideally, I'd do something like this:

mySVG.getChildByType("type1").innerHTML = "here's new text";

(With the caveat that every similar SVG has one of these "type1"` children, that can be grabbed and messed with.)

Thanks.

CodePudding user response:

It's not exactly clear what you want; it sounds like you want a way to get the text elements inside of a specific SVG?

In that case, use something like the following:

document.querySelectorAll("svg > text")[0].textContent = "I am the new string";

Now querySelectorAll() just uses CSS selectors, so you can replace svg in there with a .class, #id, or just use whatever CSS selector you want.

CodePudding user response:

You could use rather verbose class names to avoid accidentally overridden styles inherited from a global css.
E.g a BEM-like naming scheme as commonly used in scripts/libs like image sliders, media players, map helpers.

If your svg text elements are dynamically compiled you might run a function adding index based IDs/class properties:

const parentSvgs = document.querySelectorAll('.mySvg');
setAutoIds(parentSvgs);

function setAutoIds(parents) {
  parents.forEach(function(parent, p) {
    let parentIdentifier = 'mySvg__parent--'   p;
    parent.id = parentIdentifier;
    parent.classList.add(parentIdentifier);
    let children = parent.querySelectorAll('.mySvg__text');
    children.forEach(function(child, c) {
      let childIdentifier = `mySvg__text--${p}-${c}`;
      child.id = childIdentifier;
      child.classList.add(childIdentifier);
      child.classList.add(`mySvg__text--${c}`);
    })
  })
}

//auto content example
setIndexedContent(parentSvgs);

function setIndexedContent(parents) {
  parents.forEach(function(parent, p) {
    let children = parent.querySelectorAll('.mySvg__text');
    children.forEach(function(child, c) {
      child.textContent = `svg nr.${p 1} info nr.${c 1}`;
    });
  });
}

// single text element selected by ID or class
document.getElementById('mySvg__text--1-3').textContent = 'unique text by ID';
document.getElementById('mySvg__text--1-2').textContent = 'unique text by Class';
.mySvg {
  display: inline-block;
  width: 20vw;
  border: 1px dotted #ccc;
}

.mySvg__text {
  font-size: 10px;
}

.mySvg__text--0 {
  fill: orange
}

.mySvg__text--1 {
  fill: green
}

.mySvg__text--2 {
  fill: red
}
<svg  viewBox="0 0 100 100">
    <text x="50" y="25" text-anchor="middle" dominant-baseline="central" >info</text>
    <text x="50" y="50" text-anchor="middle" dominant-baseline="central" >info</text>
      <text x="50" y="75" text-anchor="middle" dominant-baseline="central" >info</text>
</svg>

<svg  viewBox="0 0 100 100">
    <text x="50" y="10" text-anchor="middle" dominant-baseline="central" >info</text>
    <text x="50" y="20" text-anchor="middle" dominant-baseline="central" >info</text>
    <text x="50" y="30" text-anchor="middle" dominant-baseline="central" >info</text>
      <text x="50" y="40" text-anchor="middle" dominant-baseline="central" >info</text>
</svg>

This way you could apply shared css styles but also select individual elements according to their global index.

  • Related