grab svg text value with javascript
Asked Answered
H

4

6

I have this javascript...

window.writeText = function(form) {
  var text;
  form.catnumber2.value = "PING";
  text = document.getElementByName('cat2Number').innerHtml;
  return alert(text);
};

But I get no alert box as expected.

The svg does not show up when I view source via view/developer/view source (I'm in chrome) BUT when I use view/developer/developer tools....I can see the following svg....

<svg height="594">
    <g ID="MasterG">
        <text name="cat2Number">"$1234"</text>
    </g>
</svg>

Any idea what I'm doing wrong? Why is it I can't see the svg code in "view source" but I can in "developer tools" ? Is that the cause of my problem? Is that why my alert box won't "alert"?

Hypnology answered 30/7, 2012 at 18:55 Comment(0)
E
8

After a couple of seconds of googling and finding this https://mcmap.net/q/1302794/-js-on-svg-getting-innerhtml-of-an-element

I created this JSFiddle example of using textContent: http://jsfiddle.net/hVyTJ/1/

The original http://jsfiddle.net/hVyTJ/ uses standard DOM traversal to get to the text element from the root SVG element. While the update targets the text element directly by ID.

As for finding attribute values you can use getAttributeNS as described here: http://www.carto.net/svg/manipulating_svg_with_dom_ecmascript/

EDIT:

As pointed out by Phrogz, a simple getAttribute call is often sufficient. Read the comment for more details.

Emery answered 30/7, 2012 at 20:12 Comment(2)
Note that SVG attributes have no namespace, and so a standard getAttribute() is equivalent (and less annoying than mySVGEl.getAttributeNS(null,"d")). (There are a few attributes that commonly appear in SVG from other specs that do have a namespace, such as XLink's xlink:href, but these are the exception.)Tadich
alert(document.getElementById('cat2Number').textContent); DID IT!!! Thanks to both you and PhrogzHypnology
M
2

For the ones who need only the displayed text, you can use the Selection API and its Range interface.

Simply using .textContent would also grab all text nodes that aren't displayed:

const svg = document.querySelector("svg");
console.log(svg.textContent);
<svg>  
  <defs>
    <desc>This text is not displayed, it shouldn't be grabbed</desc>
    <!-- same for all the new-lines in the markup -->
   </defs>
  <rect width="100%" height="100%" fill="red" />  

  <circle cx="150" cy="100" r="80" fill="green" />  

  <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>  

</svg>

Since SVG elements don't have an innerText property, we need to iterate ourselves over all text nodes, and check if when selecting them we get a BBox.

const svg = document.querySelector("svg");
const range = new Range();
let textContent = "";
const walker = document.createTreeWalker(svg, NodeFilter.SHOW_TEXT, null);
while(walker.nextNode() && walker.currentNode) {
  range.selectNode(walker.currentNode);
  if (range.getClientRects().length) {
    textContent += walker.currentNode.textContent;
  }
}
console.log(textContent);
<svg>  
  <defs>
    <desc>This text is not displayed, it shouldn't be grabbed</desc>
    <!-- same for all the new-lines in the markup -->
   </defs>
  <rect width="100%" height="100%" fill="red" />  

  <circle cx="150" cy="100" r="80" fill="green" />  

  <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>  

</svg>
Micro answered 20/12, 2022 at 3:48 Comment(1)
It's always an honor to annotate the source code with references to the SO contributors that help with the seemingly uncommon issues.Libau
S
1

you can invoke text() to return the text content of an svg:text element.

// assume svgCont is an svg element
var label = svgCont.append("svg:text").text("hello, world!");

// print the text content to the console
console.log( label.text() );
Sauncho answered 20/4, 2013 at 0:35 Comment(0)
W
1

Without all the unnecessary discussion:

Grab your SVG element:

svg = document.getElementById("my_svg_id");

Grab the inner text from the SVG:

var text = svg.textContent
Wace answered 4/10, 2022 at 17:19 Comment(2)
...consider adding .trim() to remove auto-padded \n linefeeds.Hampton
This will return a lot more text than what's displayed in <text> elements. jsfiddle.net/gLzkc7qy cc @Hampton (not sure what you or OP were after)Micro

© 2022 - 2024 — McMap. All rights reserved.