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.