2

I am trying to load an external SVG document into a simple web page so that I can use it as a basic chloropeth map. However, using <object data=""></object> in the HTML results in the SVG loading as a subdocument.

Basically I am unable to query the SVG paths by ID using jquery (ex: $('#NY').css("fill", "red") doesn't do anything). Obviously I can just cut and paste the actual SVG content into the HTML, but I'm curious if there is a way to get the SVG path stuff to load into the HTML document using <object> or similar.

The HTML:

<object data="/static/metric/img/map_US.svg" type="image/svg+xml">
</object>

Here's a shot of the DOM using the console (notice the SVG stuff is inside a #document subdocument!):

SVG Subdocument DOM

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
James
  • 2,488
  • 2
  • 28
  • 45
  • 2
    Have you considered using [`XMLHttpRequest`](http://www.w3.org/TR/XMLHttpRequest/) instead? If all you want to do is load some data and then insert it to the document that's more efficient than using . If you like js libraries, then there's http://snapsvg.io/docs/#Snap.load and https://github.com/mbostock/d3/wiki/Requests to make loading data even easier. – Erik Dahlström Aug 18 '14 at 09:19
  • @ErikDahlström I'll look into this later. I'm currently using d3 for many visualization related things. The main motivation for my question was to see if there is a "native" way to load external SVG content into HTML much like `` or any other tag. Strange that there is no straightforward way of doing this. – James Aug 21 '14 at 03:04

1 Answers1

2

I believe what you are looking for is getSVGDocument or contentDocument:

document.getElementById('thesvg').getSVGDocument().getElementById('theelement')

or

document.getElementById('thesvg').contentDocument.getElementById('theelement')

You probably want to test for both, I'm not quite sure what the compatibility is with various browsers at the moment.

Update

You can move nodes from the SVG subdocument to the main one using adoptNode. With an empty <svg> element (called target) in the main document:

o = document.getElementById('thesvg').contentDocument.getElementById('theelement');
document.adoptNode(o);
document.getElementById('target').appendChild(o);

Again, not sure what the compatibility is for this, but it works in Safari. According to the W3C DOM FAQ, this is a DOM Level 3 method. Level 2 has importNode which apparently allows a copy rather than a move. And as suggested by the same FAQ, you can always walk through the subdocument and re-create the hierarchy in the main document using createNode and friends.

jcaron
  • 17,302
  • 6
  • 32
  • 46
  • Thanks for the answer. But this seems to be a way to query the subdocuments. I am specifically looking for a way to load an SVG into the HTML via `object`, `embed`, or similar and make it part of the native DOM; i.e., *no subdocuments*. – James Aug 17 '14 at 19:56
  • Updated the answer with `adoptNode` and more. – jcaron Aug 17 '14 at 20:37
  • It works on Firefox. What a nasty way of doing things! But hey, it works... It's much more straightforward to just have the SVG stuff directly in your HTML. Cheers. – James Aug 17 '14 at 22:20
  • @James I improved a bit on this for that answer: https://stackoverflow.com/a/72804140/3795597 and made it into a one-liner: ``. Thanks for giving me the idea. – MayeulC Jun 29 '22 at 15:36