getSVGDocument returns null in FireFox and Chrome - 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

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.

Getting empty object form svg image [duplicate]

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

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

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 );
}

Problem with jquery animation and Internet explorer 8

this evening I worked very hard trying to understand html positions and jquery animation a I did an HTML page as follows:
<html>
<head>
<script src="jquery-1.5.1.min.js" type="text/javascript"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
body {
background-image: url(Cartoon_Landscape2.jpg);
}
</style>
<script type="text/javascript">
function moveDIV ( obj, x, y ) {
var element = document.getElementById(obj);
element.style.left=x;
element.style.top=y;
}
var t;
function anim1()
{
moveDIV("mariposa", screen.availWidth, screen.availHeight);
$("#mariposa").animate({left: '-84', top: '-58'}, 10000);
t=setTimeout("anim1()",22000);
//moveDIV("mariposa2", '-84', screen.availHeight);
//$("#mariposa2").animate({left: screen.availWidth, top: '-58'}, 10000);
}
function anim2()
{
moveDIV("mariposa2", '-84', screen.availHeight);
$("#mariposa2").animate({left: screen.availWidth, top: '-58'}, 10000);
t=setTimeout("anim2()",22000);
}
function callfunctions()
{
moveDIV("mariposa2", '-84', screen.availHeight);
anim1();
var b=setTimeout("anim2()",11000);
}
</script>
</head>
<body onLoad="javascript:callfunctions();" >
<div id="mariposa" style="position:fixed; overflow: hidden;">
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=4,0,0,0" name="mariposa" width="84" height="58" align="top">
<param name=movie value="mariposa.swf">
<param name=wmode value=transparent>
<param name=quality value=high>
<embed src="mariposa.swf" width="84" type="application/x-shockwave-flash" height="58" quality=high pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" wmode="transparent" align="top" name="mariposa">
</embed>
</object>
</div>
<div id="mariposa2" style="position:fixed; overflow: hidden;">
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=4,0,0,0" name="mariposa2" width="-84" height="58" align="top">
<param name=movie value="mariposa2.swf">
<param name=wmode value=transparent>
<param name=quality value=high>
<embed src="mariposa2.swf" width="84" type="application/x-shockwave-flash" height="58" quality=high pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" wmode="transparent" align="top" name="mariposa2">
</embed>
</object>
</div>
</body>
</html>
So the page shows a flash animation with diagonal motion from the left and from the right of screen.
And was perfect for me, and works nice on firefox, opera, safari , chome, but not on internet explorer 8!!, what can I do to fix this problem? =(
P.S. if I use absolute position in both DIVs, the animation works on internet explorer but unnecessary scrollbars are created.
Thanks
I see few things that may lead to various problems in your example code:
1. JavaScript
First of all, you are barely using any jQuery at all. Since you are already using jQuery then you might as well use it to its full extend and save yourself a lot of headaches. For example,
instead of implementing your own moveDIV() function you can use:
$("#id").css({left: 10, top: 10});
almost exactly how you use .animate() in your code. You can also use offset() for that depending what is better for you:
$("#id").offset({left: 10, top: 10});
Read about .offset(), .css() and
.animate() in the jQuery API docs.
By the way, instead of using:
setTimeout("anim1()",22000);
it's better to use:
setTimeout(anim1, 22000);
It does the same thing but is more efficient.
2. CSS
You may try to experiment with position: absolute or position: relative where you have position: fixed.
3. HTML
You have no doctype and the IE may try to render your page in quirks mode. To use standards mode add a doctype at the very beginning of your HTML: <!doctype html>
In fact IE8 it may even use the IE7 rendering engine if it thinks it would be better for your website. If you want to make sure that you are always rendered by the best rendering engine in IE you should also add: <meta http-equiv="X-UA-Compatible" content="IE=Edge">
Also, when you make sure that your website works on IE8 then you can also make it use the Google Chrome Frame plugin if it is available: <meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1">
All in all, the beginning of your HTML should look something like this
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1" >
... and the rest of your HTML
Those are just the main things I see in your code that you may consider changing. I don't know if doing it solves your problem but even if it doesn't it may free you from having to deal with other problems later.

Categories