Createelement VS. Createelementns

createElement vs. createElementNS

To understand the problem namespaces are trying to solve, consider file extensions. 3-letter file extensions have done a really bad job of describing the content of files. They're ambiguous and don't carry version info. XML namespaces use a larger space of strings, URIs, to solve the same problem, and use short prefixes so you can succinctly mix multiple kinds of XML in the same document.

What's the purpose of namespace if there is only one name space?

There are many namespaces used to identify different kinds of XML, and different versions of those kind.

SVG and MathML are two kinds of XML each with their own namespaces that can be embedded in HTML5, and they often use XLink, another XML namespace. Many other XML schemas, with corresponding namespaces, are used for passing messages between clients and servers and for data storage.

XHTML is an attempt to express HTML as valid XML. It has its own namespace.

So we use createElementNS(ns_string, 'svg') And then setAttributeNS(null,,). Why? Why not setAttributeNS('my_ns',,)???

You should probably try to consistently use setAttributeNS with a namespace URI when using createElementNS with a namespace URI.

XML was defined in multiple steps. The first version of the spec said nothing about namespaces but left enough syntax so that XML with namespaces could be specified on top of XML without namespaces by using prefixes and special xmlns attributes. The XML specification says:

"The Namespaces in XML Recommendation [XML Names] assigns a meaning to names containing colon characters. Therefore, authors should not use the colon in XML names except for namespace purposes, but XML processors must accept the colon as a name character."

XML namespaces let XML processing applications know what they're dealing with, and allow multiple kinds of XML to be mixed together in the same document.

Why ns_string must be "http://www.w3.org/2000/svg"

This includes the year that version of SVG was standardized, 2000, so it carries useful information.

When used with xmlns:svg it also lets the browser know that the svg: prefix means SVG and not some other dialect of XML.

Why is it necessary to use `document.createElementNS` when adding `svg` tags to an HTML document via JS?

If you call document.createElement("a") which <a> should it create? The HTML one or the SVG one? There lies the problem. Ditto script etc. You're not giving the browser any way to guess till the appendChild step and by then it's too late.

You can do this without namespaces via innerHTML because that takes a string with all the markup so the browser can parse and add in one step and thereby infer the correct namespace.

Or just create a wrapper function

function createSVGElement(tag) {
return document.createElementNS('http://www.w3.org/2000/svg', tag)
}

Does createElementNS work consistently offline? Specifically with the SVG namespace

http://www.w3.org/2000/svg is not only an URL it is an XML namespace. XML namespaces can be URLs and must be URIs. An example for an namespace that is not an URL would be urn:ietf:params:xml:ns:vcard-4.0. The page is not meaningless. It contains informations about the XML namespace and links.

XML namespaces define the format/standard an element or attribute node is part of. They have to be unique, using a domain as a part of it avoids conflicts and allows for some documentation.

The reason for you problem might be that you open the html file directly from the file system and the HTTP headers are missing. This changes how a browser handles a file. How depends on the browser the OS and the file.

Element created with createElementNS doesn't show

Create a SVG:

var svg = document.createElementNS(ns, 'svg');

First function:

function createSVG() { ... }

Second function:

function createSVGCircle() { createSVG() ... }

Or separated:

createSVG();
createSVGCircle();

Example

What are namespaces in HTML?

Namespaces make it possible for different types of XML¹ to have the same tag with different meanings. Here's an excerpt from Namespaces crash course on MDN:

It has been a long standing goal of the W3C to make it possible for different types of XML based content to be mixed together in the same XML file. For example, SVG and MathML might be incorporated directly into an XHTML based scientific document. Being able to mix content types like this has many advantages, but it also required a very real problem to be solved.

Naturally, each XML dialect defines the meaning of the markup element names described in its specification. The problem with mixing content from different XML dialects in a single XML document is that the elements defined by one dialect may have the same name as elements defined by another. For example, both XHTML and SVG have a element. How should the user agent distinguish between the two? In fact how does the user agent tell when XML content is something it knows about, and not just a meaningless XML file containing arbitrary element names unknown to it?

In your specific example, the difference is that createElement("svg") creates an HTML element with the tag name svg (which doesn't exist, there is no HTML element with that tag name). But createElementNS("http://www.w3.org/2000/svg", "svg") creates an SVG element with the tag name svg (which does exist).

It matters because the SVG element has defined behavior and various methods and such you may want. Trying to create it as an HTML element, you don't get those behaviors and methods:

const a = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const b = document.createElement("svg");

console.log("a instanceof SVGSVGElement?", a instanceof SVGSVGElement); // a instanceof SVGSVGElement? true
console.log("b instanceof SVGSVGElement?", b instanceof SVGSVGElement); // b instanceof SVGSVGElement? false

console.log("typeof a.currentScale:", typeof a.currentScale); // typeof a.currentScale: number
console.log("typeof b.currentScale:", typeof b.currentScale); // typeof b.currentScale: undefined

JavaScript createElementNS and SVG

I hope, the following example will help you:

function CreateSVG() {    var xmlns = "http://www.w3.org/2000/svg";    var boxWidth = 300;    var boxHeight = 300;
var svgElem = document.createElementNS(xmlns, "svg"); svgElem.setAttributeNS(null, "viewBox", "0 0 " + boxWidth + " " + boxHeight); svgElem.setAttributeNS(null, "width", boxWidth); svgElem.setAttributeNS(null, "height", boxHeight); svgElem.style.display = "block";
var g = document.createElementNS(xmlns, "g"); svgElem.appendChild(g); g.setAttributeNS(null, 'transform', 'matrix(1,0,0,-1,0,300)');
// draw linear gradient var defs = document.createElementNS(xmlns, "defs"); var grad = document.createElementNS(xmlns, "linearGradient"); grad.setAttributeNS(null, "id", "gradient"); grad.setAttributeNS(null, "x1", "0%"); grad.setAttributeNS(null, "x2", "0%"); grad.setAttributeNS(null, "y1", "100%"); grad.setAttributeNS(null, "y2", "0%"); var stopTop = document.createElementNS(xmlns, "stop"); stopTop.setAttributeNS(null, "offset", "0%"); stopTop.setAttributeNS(null, "stop-color", "#ff0000"); grad.appendChild(stopTop); var stopBottom = document.createElementNS(xmlns, "stop"); stopBottom.setAttributeNS(null, "offset", "100%"); stopBottom.setAttributeNS(null, "stop-color", "#0000ff"); grad.appendChild(stopBottom); defs.appendChild(grad); g.appendChild(defs);
// draw borders var coords = "M 0, 0"; coords += " l 0, 300"; coords += " l 300, 0"; coords += " l 0, -300"; coords += " l -300, 0";
var path = document.createElementNS(xmlns, "path"); path.setAttributeNS(null, 'stroke', "#000000"); path.setAttributeNS(null, 'stroke-width', 10); path.setAttributeNS(null, 'stroke-linejoin', "round"); path.setAttributeNS(null, 'd', coords); path.setAttributeNS(null, 'fill', "url(#gradient)"); path.setAttributeNS(null, 'opacity', 1.0); g.appendChild(path);
var svgContainer = document.getElementById("svgContainer"); svgContainer.appendChild(svgElem);}
#svgContainer {  width: 400px;  height: 400px;  background-color: #a0a0a0;}
<body onload="CreateSVG()">    <div id="svgContainer"></div></body>

Is there a difference between `new Image()` and `document.createElement('img')`?

I couldn't find any detailed reference but based on the comment in the MDC - HTMLImageElement example, it seems that Image is part of DOM level 0 whereas document.createElement is part of DOM level 2.

DOM level 0 was invented by Netscape and provided a way to access the certain elements of the website. Basically all browsers support it for backwards compatibility.

But to be honest, I don't understand why the Image constructor exists there, because, as far as I understood it, there was no way to manipulate the document with DOM level 0. Maybe it was only used internally by the browser to create the objects.

DOM level 2 is an official standard developed by the W3C.

For more information about the DOM levels, have a look at at quirksmode.org - Level 0 DOM and Wikipedia.


I've read somewhere that Image, Form, and Element is called host objects, is this true?

Yes.

If it is, what are host objects?

The ECMAScript specification motivates host objects this way:

ECMAScript is an object-oriented programming language for performing computations and manipulating computational objects within a host environment. ECMAScript as defined here is not intended to be computationally self-sufficient; indeed, there are no provisions in this specification for input of external data or output of computed results. Instead, it is expected that the computational environment of an ECMAScript program will provide not only the objects and other facilities described in this specification but also certain environment-specific host objects, whose description and behaviour are beyond the scope of this specification except to indicate that they may provide certain properties that can be accessed and certain functions that can be called from an ECMAScript program.

and

host object
object supplied by the host environment to complete the execution environment of ECMAScript.

NOTE Any object that is not native is a host object.

So any object that is not defined in the specification and provided by the environment is a host object. These are for example in a browser (among others): window, document and console.

SVG not working when inserted from Javascript

Use createElementNS instead of createElement for SVG elements.

const ns = 'http://www.w3.org/2000/svg';
class Spinner { constructor(target) { this.target = document.getElementById(target);
const spinner = document.createElementNS(ns, 'svg'); spinner.setAttribute('width', '100'); spinner.setAttribute('height', '100');
const spinnerPath = document.createElementNS(ns, 'circle'); spinnerPath.setAttribute('fill', 'red'); spinnerPath.setAttribute('stroke', 'black'); spinnerPath.setAttribute('stroke-width', '3'); spinnerPath.setAttribute('cx', '50'); spinnerPath.setAttribute('cy', '50'); spinnerPath.setAttribute('r', '40');
spinner.appendChild(spinnerPath);
this.target.appendChild(spinner); }}
new Spinner('here');
<div id="here"></div>


Related Topics



Leave a reply



Submit