By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,203 Members | 1,560 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,203 IT Pros & Developers. It's quick & easy.

Building SVG document Using DOM Interface Inside HTML Document

P: n/a
SMH

Normally an SVG document is loaded/parsed/interpreted inside an HTML
document using an 'object' (or 'embed') element, although there are
supposedly other ways too. The problem is, the SVG document must be
static this way.

I want to use the DOM interface to build SVG dynamically inside an HTML
document. I am guessing I can build it inside HTML within an 'object' (or
maybe 'iframe'?) element.

My intentions/goals:

In Javascript, I construct an object 'embedSVG' which has properties and
methods for creating valid SVG elements and setting their attributes and
attribute values.

During construction, the SVG document is created with its root element.
During debugging in FF 2.0 (I'll work on an MSIE-compatible format later),
I am using the Mozilla DOM Inspector and comparing nodes when the
'object' element is loading a valid external SVG document, and when I am
appending the child representing the SVG document created by the DOM
functions.

However the child node (#document) does not specify 'svg' as the root
element, but instead 'HTML'. Something is not working.

Here is the relevant code in 'ScriptTest.html' which is the HTML in which
the SVG is supposed to be embedded. Below it is the relevant code for
'svglib.js' which is supposed to contain code for building the SVG
dynamically.

What this code is supposed to do is load the HTML page and execute the
anonymous script, and draw a navy blue-bordered yellow rectangle on a
blank page. This is similar to the example in the SVG 1.1 W3C
Recommendation on page 202 of the 719-page PDF.

I am getting an exception when embedSVG object placeInHTML() method is
called: NS_ERROR_DOM_HIERARCHY_REQUEST_ERR. I find in DOM Inspector in
spite of or after the exception that a document is placed as a child of
the object element, but it is HTML, with a default 'head', 'title',
'body' elements placed.

Where am I blowing it?

===== start ScriptTest.html excerpt =====
..
..
..
<body>

<object id="insertSVG"></object>

<script type="text/javascript">
var svgHTMLnode = document.getElementById("insertSVG");
var svgObj = new embedSVG(400, 200);
svgObj.placeInHTML(svgHTMLnode);
svgObj.setFill("yellow");
svgObj.setStroke("navy");
svgObj.setStrokeWidth("10");
svgObj.drawRect(20, 20, 200, 100);
</script>
</body>
</html>
===== end ScriptTest.html excerpt =====

====== start svglib.js excerpt ======

function embedSVG (docWidth, docHeight )
{
//arg checking

var svgXMLdoc;
var namespaceURI = "http://www.w3.org/2000/svg";
var qualifiedName = "svg";
var doctype = null;
this.svgXMLdoc = svgXMLdoc =
document.implementation.createDocument(namespaceUR I,
qualifiedName, doctype);

var rootElem = svgXMLdoc.firstChild;
rootElem.setAttribute("xmlns", "http://www.w3.org/2000/svg");
rootElem.setAttribute("height", String(docHeight));
rootElem.setAttribute("width", String(docWidth));
this.rootElement = rootElem;
this.fill = "";
this.setFill = function (fillString) { this.fill = fillString; };
this.stroke = "";
this.setStroke = function (strokeString) {
this.stroke = strokeString; };
this.strokeWidth = "";
this.setStrokeWidth = function (strokeWidthString) {
this.strokeWidth = strokeWidthString;
};
this.placeInHTML = function (htmlNode) {
return ((htmlNode.appendChild(this.svgXMLdoc));
};
this.drawRect = function (left, top, width, height,
roundedXradius, roundedYradius) {
var docElem = this.svgXMLdoc.createElement("rect");

// arg checking
docElem.setAttribute("x", left);
docElem.setAttribute("y", top);
docElem.setAttribute("width", width);
docElem.setAttribute("height", height);
docElem.setAttribute("rx", roundedXradius);
docElem.setAttribute("ry", roundedYradius);
docElem.setAttribute("fill", this.fill);
docElem.setAttribute("stroke", this.stroke);
docElem.setAttribute("strokeWidth", this.strokeWidth);
this.rootElement.appendChild(docElem);
return (docElem);
};
}
====== end svglib.js excerpt ======

I am being guided by N.C. Zakas' Professional JavaScript for Web
Developers.

Mar 17 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
SMH <se********@gmail.comwrote:
>Normally an SVG document is loaded/parsed/interpreted inside an HTML
document using an 'object' (or 'embed') element, although there are
supposedly other ways too.
Using mixed namespaces, this requires serving the document as XHTML.
Demo: http://www.spartanicus.utvinternet.i...amespace.xhtml
(Note that MS IE does not support XHTML)
>The problem is, the SVG document must be
static this way.
If by that you mean it has to have predefined dimensions, then you are
correct. That limitation does not exist for mixed namespace documents.
>My intentions/goals:

In Javascript, I construct an object 'embedSVG' which has properties and
methods for creating valid SVG elements and setting their attributes and
attribute values.

During construction, the SVG document is created with its root element.
During debugging in FF 2.0 (I'll work on an MSIE-compatible format later),
I am using the Mozilla DOM Inspector and comparing nodes when the
'object' element is loading a valid external SVG document, and when I am
appending the child representing the SVG document created by the DOM
functions.

However the child node (#document) does not specify 'svg' as the root
element, but instead 'HTML'. Something is not working.
I'm guessing that you want to use JS to determine the size of the
viewport that the SVG will need, and then dynamically set that size on
the object or iframe element in the mother document?

The JS needed to determine the viewport size needed by the SVG has to
run in the SVG file, the resulting values should then be used in the
mother HTML document. I don't know enough about JS to say if that's
possible, but I doubt it.

--
Spartanicus
Mar 17 '07 #2

P: n/a
On Mar 17, 9:15 am, SMH <sevis.a...@gmail.comwrote:
Normally an SVG document is loaded/parsed/interpreted inside an HTML
document using an 'object' (or 'embed') element, although there are
supposedly other ways too. The problem is, the SVG document must be
static this way.

I want to use the DOM interface to build SVG dynamically inside an HTML
document. I am guessing I can build it inside HTML within an 'object' (or
maybe 'iframe'?) element.

My intentions/goals:

In Javascript, I construct an object 'embedSVG' which has properties and
methods for creating valid SVG elements and setting their attributes and
attribute values.

During construction, the SVG document is created with its root element.
During debugging in FF 2.0 (I'll work on an MSIE-compatible format later),
I am using the Mozilla DOM Inspector and comparing nodes when the
'object' element is loading a valid external SVG document, and when I am
appending the child representing the SVG document created by the DOM
functions.

However the child node (#document) does not specify 'svg' as the root
element, but instead 'HTML'. Something is not working.

Here is the relevant code in 'ScriptTest.html' which is the HTML in which
the SVG is supposed to be embedded. Below it is the relevant code for
'svglib.js' which is supposed to contain code for building the SVG
dynamically.

What this code is supposed to do is load the HTML page and execute the
anonymous script, and draw a navy blue-bordered yellow rectangle on a
blank page. This is similar to the example in the SVG 1.1 W3C
Recommendation on page 202 of the 719-page PDF.

I am getting an exception when embedSVG object placeInHTML() method is
called: NS_ERROR_DOM_HIERARCHY_REQUEST_ERR. I find in DOM Inspector in
spite of or after the exception that a document is placed as a child of
the object element, but it is HTML, with a default 'head', 'title',
'body' elements placed.

Where am I blowing it?

===== start ScriptTest.html excerpt =====
.
.
.
<body>

<object id="insertSVG"></object>

<script type="text/javascript">
var svgHTMLnode = document.getElementById("insertSVG");
var svgObj = new embedSVG(400, 200);
svgObj.placeInHTML(svgHTMLnode);
svgObj.setFill("yellow");
svgObj.setStroke("navy");
svgObj.setStrokeWidth("10");
svgObj.drawRect(20, 20, 200, 100);
</script>
</body>
</html>
===== end ScriptTest.html excerpt =====

====== start svglib.js excerpt ======

function embedSVG (docWidth, docHeight )
{
//arg checking

var svgXMLdoc;
var namespaceURI = "http://www.w3.org/2000/svg";
var qualifiedName = "svg";
var doctype = null;
this.svgXMLdoc = svgXMLdoc =
document.implementation.createDocument(namespaceUR I,
qualifiedName, doctype);

var rootElem = svgXMLdoc.firstChild;
rootElem.setAttribute("xmlns", "http://www.w3.org/2000/svg");
rootElem.setAttribute("height", String(docHeight));
rootElem.setAttribute("width", String(docWidth));
this.rootElement = rootElem;
this.fill = "";
this.setFill = function (fillString) { this.fill = fillString; };
this.stroke = "";
this.setStroke = function (strokeString) {
this.stroke = strokeString; };
this.strokeWidth = "";
this.setStrokeWidth = function (strokeWidthString) {
this.strokeWidth = strokeWidthString;
};
this.placeInHTML = function (htmlNode) {
return ((htmlNode.appendChild(this.svgXMLdoc));
};
this.drawRect = function (left, top, width, height,
roundedXradius, roundedYradius) {
var docElem = this.svgXMLdoc.createElement("rect");

// arg checking
docElem.setAttribute("x", left);
docElem.setAttribute("y", top);
docElem.setAttribute("width", width);
docElem.setAttribute("height", height);
docElem.setAttribute("rx", roundedXradius);
docElem.setAttribute("ry", roundedYradius);
docElem.setAttribute("fill", this.fill);
docElem.setAttribute("stroke", this.stroke);
docElem.setAttribute("strokeWidth", this.strokeWidth);
this.rootElement.appendChild(docElem);
return (docElem);
};}

====== end svglib.js excerpt ======

I am being guided by N.C. Zakas' Professional JavaScript for Web
Developers.
You're making things more complicated than they need to be. You don't
need to use an iframe or object tag to use SVG; just use a DIV. Be
sure, however, to include the appropriate XML namespaces on your HTML
tag; the SVG NS (http://www.w3.org/2000/svg) for starters, but you
might also look at including XLink (http://www.w3.org/1999/xlink) for
embedded links on SVG elements.

Another thing to keep in mind when DOM scripting SVG is that SVG is
strict XML, unlike typical DHTML scripting. So you need to use
namespace-aware DOM functions, such as createElementNS and
setAttributeNS. Use your SVG namespaceURI when creating elements
using createElementNS, but you can simply use 'null' for
setAttributeNS. Try that out and let us know how it works.

-D

Mar 17 '07 #3

P: n/a
SMH
Spartanicus <in*****@invalid.invalidwrote in comp.lang.javascript:
SMH <se********@gmail.comwrote:
>>Normally an SVG document is loaded/parsed/interpreted inside an HTML
document using an 'object' (or 'embed') element, although there are
supposedly other ways too.

Using mixed namespaces, this requires serving the document as XHTML.
Demo: http://www.spartanicus.utvinternet.i...amespace.xhtml
(Note that MS IE does not support XHTML)
>>The problem is, the SVG document must be
static this way.

If by that you mean it has to have predefined dimensions, then you are
correct. That limitation does not exist for mixed namespace documents.
>>My intentions/goals:

In Javascript, I construct an object 'embedSVG' which has properties
and methods for creating valid SVG elements and setting their
attributes and attribute values.

During construction, the SVG document is created with its root
element. During debugging in FF 2.0 (I'll work on an MSIE-compatible
format later), I am using the Mozilla DOM Inspector and comparing
nodes when the 'object' element is loading a valid external SVG
document, and when I am appending the child representing the SVG
document created by the DOM functions.

However the child node (#document) does not specify 'svg' as the root
element, but instead 'HTML'. Something is not working.

I'm guessing that you want to use JS to determine the size of the
viewport that the SVG will need, and then dynamically set that size on
the object or iframe element in the mother document?

The JS needed to determine the viewport size needed by the SVG has to
run in the SVG file, the resulting values should then be used in the
mother HTML document. I don't know enough about JS to say if that's
possible, but I doubt it.
You're absolutely right that I didn't really explain my ultimate need for
this.

I have a very interactive HTML document that takes form entries
representing input data that will be statistically evaluated. The results
will be presented graphically through SVG (that is, the plot axes have to
be drawn, the plot scale will be rendered, the plot points (as a scatter
plot or maybe column chart). Of course, all these are unknown at "run
time" which is why the script has to write the SVG document content
dynamically. I decided to go with SVG because it is a W3C
"recommendation" (i.e., standard). I am aware of a lot of other hacks out
there (e.g., libraries of script manipulating CSS-controlled painted
DIVs), but without having used them, I am guessing that they don't always
work in every conceivable situation (without more hacking) and give hope
for wide cross-browser compatibility.

I have been running around Google and the Internet to see if I can stumble
upon something that someone has used.

I have seen the createElementNS() method mentioned before but never really
used it. Poster David Golightly mentions it also, so I will try to apply
his recommendations and report back.

After making it work in FF, I will try to make it work in IE (a must for
all the target users of this page interactivity). I am guessing that use
of ActiveXObjects often makes more things possible in the MS sort of way.
Yes, I know that working with MS scripting is beyond the standard, but
that is the one exception in scripting beyond the perimeter than I am
willing to make.
Mar 18 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.