Getting empty object form svg image [duplicate] - javascript

Is getSVGDocument broken? Obsolete?
Because when I "run" the following:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>SVG Embedded - Chapter 07</title>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.css">
<link rel="stylesheet" href="../assets/style.css">
<style>
body { margin: 1em; }
svg { border: 1px solid silver; }
rect, text { fill: white; }
circle { fill: black; }
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" height="200" width="300">
<rect width="100%" height="100%" fill="black" />
<circle cx="150" cy="100" r="80" fill="white" />
<text x="150" y="125" font-size="60" text-anchor="middle">SVG</text>
</svg>
<embed src="../assets/svg.svg"></embed>
<object data="../assets/svg.svg"></object>
<script>
document.addEventListener('DOMContentLoaded',function() {
'use strict';
var rects = document.querySelectorAll('svg'),
embed = document.querySelector('embed').getSVGDocument();
console.log(rects.length);
console.log(embed,embed.childNodes.length);
},false);
</script>
</body>
</html>
then wait for all the 3 SVG to be (loaded and) displayed, and input inside the console: document.getElementsByTagName('embed')[0].getSVGDocument() it returns null
Full page (with files) can be downloaded there:
https://github.com/stopsatgreen/modernwebbook/blob/master/Code%20Examples/Chapter%2007/svg-embedded.html
Note: I'll try to have the page running in JS Bin.
EDIT:
Could the problem be this? SVG not working when access on localhost. Why?
If so, how to fix it without configuring a (local) webserver?

The getSVGDocument() method is deprecated. The recommended way is to use the contentDocument attribute instead.
See here

Found how to work around this, it's a security related issue.
Chrome
Close all running chrome instances first. Then start Chrome executable with a command line flag:
chrome --allow-file-access-from-files
On Windows, the easiest is probably to create a special shortcut which has added flag (right-click on shortcut -> properties -> target).
Firefox
Go to about:config
Find security.fileuri.strict_origin_policy parameter
Set it to false
Got it there: https://github.com/mrdoob/three.js/wiki/How-to-run-things-locally

Related

If I am embedding an SVG using an <object> tag, is it possible to use normal DOM methods in JS to access the children elements?

If I am embedding an SVG using an <object> tag, is it possible to use normal DOM methods to access the children elements?
Example
First a simple SVG:
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"
viewBox="0,0 100, 100">
<defs>
<style>
#cls-1 {
fill: none;
stroke: #000;
stroke-width: 4;
}
</style>
</defs>
<title>Circles</title>
<g id="cls-1">
<circle cx="30" cy="30" r="10" />
<circle cx="60" cy="60" r="10" />
</g>
</svg>
Then an HTML file that embeds the SVG using and tries to access the group defined in the SVG within a script:
<html>
<body>
<object
type="image/svg+xml"
height="200px"
data="mysvg.svg"
></object>
<button onclick="myAnimate()" />
<script>
const myAnimate = () => {
const group = document.getElementById("cls-1");
};
</script>
</body>
</html>
Wy doesn't this work?
I see in the devtools that the first child of this is #document. So it seems to have it's own DOM, I think I read this, but still have not wrapped my head around how it works.
Is there a way to access the element with id "cls-1" from JS?
EDIT: one way to make this work is to add the script within the svg itself; the DOM methods work normally for the DOM in the SVG

Access DOM of <object> or <embed>

My index.html is
<object id="embed" data="test.html" width="500" height="500"
type="text/xml"></object>
<script>
var test = document.getElementById("test");
var embed = document.getElementById("embed");
test.style.fill = "purple";
</script>
My test.html is
<style>
#test {
cx: 80%;
fill: green;
}
</style>
<svg width="500" height="500">
<circle id="test" cx="50%" cy="50%" r="40%"
stroke="black" stroke-width="1" fill="red" />
</svg>
I would like to apply css from the parent document to the loaded svg. I would also like to manipulate the svg using javascript in the parent document. The css works. JavaScript also works. They both modify position and fill, but they only work from the test.html document.
How do I manipulate and style embedded SVGs? I have a folder full of them and they can be mixed and relabeled, which is necessary for my larger project. I got a David Lynch plot sized headache reading up on the trainwreck of html imports and am avoiding them for now.
Prefer no jQuery.

Why is my canvas embedded in an inline SVG not updating?

It seems like a contrived problem but I am trying to make a proof of concept of an HTML 5 document, containing inline SVG, which itself contains a <foreignObject> element with an HTML canvas inside. I then want to call a JavaScript function to draw on the canvas.
(How I got here: I want to use SVG as a format for defining an animated graphical view which can contain graphs, which are animated by replacing a dummy element in the SVG with a live graph using JavaScript / ECMAScript, and one of the JavaScript libraries we are considering to generate the graphs (Flot) uses an HTML canvas for the view, so I want to inject this canvas into the SVG view. A further complication is we ideally want this system to run on local files, on the file:// protocol, meaning we can't run scripts on external files (e.g. referenced with <object> or <iframe>) because browsers block them, hence the inline SVG.)
Here is an HTML source illustrating the problem:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Canvas Test</title>
<script type="text/javascript">
function draw_box() {
var canvas = document.getElementById("box_canvas");
var context = canvas.getContext("2d");
context.fillRect(50, 20, 50, 60);
}
</script>
</head>
<body>
<h1>Canvas Test
<p>
<svg width="400" viewBox="-10 -10 268 108">
<rect style="fill: #a0a0a0" x="8" y="8" width="240" height="80" rx="40" ry="40"/>
<g>
<rect style="fill: #0000ff" x="0" y="0" width="240" height="80" rx="40" ry="40"/>
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke-linejoin: round; stroke: #000000" x="0" y="0" width="240" height="80" rx="40" ry="40"/>
<foreignObject x="120" y="25" width="150" height="100">
<canvas id="box_canvas" width="150" height="100" style="border:1px dotted;float:left">Canvas alt text</canvas>
</foreignObject>
</g>
</svg>
<p>
<button type="button" onclick="draw_box();return false">Animate</button>
</body>
</html>
The above page doesn't display the canvas at all in IE 11. In the latest version of Chrome it displays the canvas, but the effects of the JavaScript function called by the button - drawing the black box - only show up if you click on the SVG image.
What I need to know:
1) Is there something wrong with what I've written - e.g. am I missing some function call to make the SVG or foreignObject update after I have drawn on the canvas?
2) Is this a lost cause? Is the specification of <foreignObject> etc. immature enough that I could never be confident that this will work, even if we can control what browser the user views the document in? It's actually fine if this is the case because we can just say going forward that we need our graph library to generate SVG and not HTML.
Thanks a lot

getSVGDocument returns null in FireFox and Chrome

Is getSVGDocument broken? Obsolete?
Because when I "run" the following:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>SVG Embedded - Chapter 07</title>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.css">
<link rel="stylesheet" href="../assets/style.css">
<style>
body { margin: 1em; }
svg { border: 1px solid silver; }
rect, text { fill: white; }
circle { fill: black; }
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" height="200" width="300">
<rect width="100%" height="100%" fill="black" />
<circle cx="150" cy="100" r="80" fill="white" />
<text x="150" y="125" font-size="60" text-anchor="middle">SVG</text>
</svg>
<embed src="../assets/svg.svg"></embed>
<object data="../assets/svg.svg"></object>
<script>
document.addEventListener('DOMContentLoaded',function() {
'use strict';
var rects = document.querySelectorAll('svg'),
embed = document.querySelector('embed').getSVGDocument();
console.log(rects.length);
console.log(embed,embed.childNodes.length);
},false);
</script>
</body>
</html>
then wait for all the 3 SVG to be (loaded and) displayed, and input inside the console: document.getElementsByTagName('embed')[0].getSVGDocument() it returns null
Full page (with files) can be downloaded there:
https://github.com/stopsatgreen/modernwebbook/blob/master/Code%20Examples/Chapter%2007/svg-embedded.html
Note: I'll try to have the page running in JS Bin.
EDIT:
Could the problem be this? SVG not working when access on localhost. Why?
If so, how to fix it without configuring a (local) webserver?
The getSVGDocument() method is deprecated. The recommended way is to use the contentDocument attribute instead.
See here
Found how to work around this, it's a security related issue.
Chrome
Close all running chrome instances first. Then start Chrome executable with a command line flag:
chrome --allow-file-access-from-files
On Windows, the easiest is probably to create a special shortcut which has added flag (right-click on shortcut -> properties -> target).
Firefox
Go to about:config
Find security.fileuri.strict_origin_policy parameter
Set it to false
Got it there: https://github.com/mrdoob/three.js/wiki/How-to-run-things-locally

Snap.load() external SVG fails to Load

PROBLEM:
I'm using Snap.svg to create some basic interactive graphics, but for some reason I can't get my external SVG file to load using Snap.load(). I've pulled code straight from the tutorial at snap.io and checked and double-checked the docs. My SVG file renders in the browser fine, it just doesn't display inside the Snap SVG. Other shapes (i.e. not pulled in using Snap.load() ) do display.
CODE:
I've boiled my example down to the most simple HTML and SVG files imaginable, and the Snap.load() method still isn't working for me. Does anyone see what I'm missing?
HTML:
<head>
<style media="screen">
#svg {
width: 300px;
height: 300px;
}
</style>
<script src="snap.svg-min.js"></script>
<meta charset=utf-8 />
</head>
<body>
<svg id="svg"></svg>
<script type="text/javascript">
var s = Snap("#svg");
Snap.load("svgtest.svg");
</script>
</body>
SVG (originally exported from Illustrator):
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<rect x="14" y="33" fill="#2BB673" width="70" height="30"/>
</svg>
UPDATE:
Updated the code as per #Ian's suggestion -
var s = Snap("#svg");
Snap.load("http://www.w3.org/TR/SVG/images/struct/Use01.svg", onSVGLoaded ) ;
function onSVGLoaded( data ){
s.append( data );
}
- but still no display of external SVG. I tried using an SVG from w3.org just to be sure it wan't a problem with the file itself or my domain.
The load function takes a callback, as loading can take some time. So I think you would do something like the following...
var s = Snap("#svg");
Snap.load("svgtest.svg", onSVGLoaded ) ;
function onSVGLoaded( data ){
s.append( data );
}
Edit: There may be some access control issues if not accessing from the same server as the script, check the console log for any errors.
I was having exactly this problem in Internet Explorer only, and it turned out to be because the SVG file I was loading in was a minified one from which the doctype had been removed. Other browsers were ok without the doctype, but leaving the doctype in fixed the problem in IE as well:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
In case, like me, you're using Grunt to minify SVGs, you can leave the doctype in by adding the following option to your Gruntfile:
svgmin: {
options: {
plugins: [
{ removeDoctype: false }
]
}
// etc...
}
There is a small bug in the distribution - see https://github.com/adobe-webplatform/Snap.svg/issues/196. The suggested fix works correctly. The online demo works because it is referencing a much older build of the library.
With version 0.5.1 installed. The code in the correct answer above needs to be re-written as follows to work:
var s = Snap();
Snap.load("svgtest.svg", onSVGLoaded ) ;
function onSVGLoaded( data ){
s.append( data );
}

Categories