D3.js - Is the "svg:" in "svg:rect" a must? - javascript

For example:
svg.append("svg:rect");
What if I drop "svg:"? It seems to work without "svg:". Any potential problems for dropping it?
Is "svg:" a d3 specific thing or it is generally required when svg
elements are used?

From the d3.js append() documentation
The name may be specified either as a constant string or as a function that returns the DOM element to append. When the name is specified as a string, it may have a namespace prefix of the form "namespace:tag". For example, "svg:text" will create a "text" element in the SVG namespace. By default, D3 supports svg, xhtml, xlink, xml and xmlns namespaces. Additional namespaces can be registered by adding to d3.ns.prefix. If no namespace is specified, then the namespace will be inherited from the enclosing element; or, if the name is one of the known prefixes, the corresponding namespace will be used (for example, "svg" implies "svg:svg").
So namespaces are (in most cases) optional since this commit.

The svg: part specifies the namespace to be used for the element. In particular, svg:rect means that the rect should be interpreted in the SVG namespace. This is relevant because not all types of elements exist in all namespaces (e.g. HTML does not have rects).
You do not normally need to specify this explicitly in recent versions of D3 as the namespace is derived from the context. In some cases, you do need to specify it to have the document interpreted properly. A notable example is when using foreignObject in SVG, which allows you to embed non-SVG content, see this example. Here it is necessary to specify xhtml as the namespace for the appended body element as the context is SVG and it would be interpreted incorrectly.

Related

Why can't a certain DOM element have CSS styles

While developing an Angular app I've come across the following issue: an SVG element didn't have styles from its class (even though it was defined in <styles> tag) and what's more peculiar (and the point of the question): Chrome and Firefox DevTools didn't allow adding element styles manually.
Note the missing element.styles block in the right pane.
However, if I edit container element HTML and just copy and paste back the markup - it suddenly appears and everything works as expected. So this must happen due to the way the element is added to DOM programmatically. And since this behaviour is identical in both Chrome and Firefox, it is most likely a feature, rather than a bug.
So how can this be achieved purposedly?
P.S. For those interested in Angular part, here is a GitHub issue that I reported for this case (also contains a reproduction repo): https://github.com/angular/material2/issues/15727
So I've found the answer myself. TL;DR: element was created with document.createElementNS with an unknown namespace (or empty), which made it an Element, rather than SVGElement. Styles are not defined for base Elements according to the specification.
So obviously the key was to check the type of the element - and both Chrome and Firefox have shown that that SVG is created as a base Element:
The next question was how did it happen. TL;DR for this section: due to a bug in Angular's new experimental compiler (probably) it was added with an invalid namespace and the rest is according to specification.
Search through Angular's source revealed the way it creates elements: createElementNS.
Quick experiment with that function has proven the initial guess that the problem was with the element's interface (Element), and it can be reproduced by passing an invalid namespace.
And DOM specification revealed exactly why does that happen:
createElementNS steps:
The internal createElementNS steps...:
...
4. Return the result of creating an element given document, localName, namespace, prefix, is, and with the synchronous custom elements flag set.
Creating an element is defined as follows:
To create an element, given a document, localName, namespace, and optional prefix, is, and synchronous custom elements flag, run these steps:
...
4. Let definition be the result of looking up a custom element definition given document, namespace, localName, and is.
Looked up definition turns out to be NULL in this case:
To look up a custom element definition, given a document, namespace, localName, and is, perform the following steps. They will return either a custom element definition or null:
1. If namespace is not the HTML namespace, return null.
Returning to createElementNS steps from before:
...
7. Otherwise: [definition is null]
Let interface be the element interface for localName and namespace.
Set result to a new element that implements interface, with no attributes, namespace set to namespace, namespace prefix set to prefix, local name set to localName, custom element state set to "uncustomized", custom element definition set to null, is value set to is, and node document set to document.
...
And finally, the element interface is defined as follows:
The element interface for any name and namespace is Element, unless stated otherwise.
As for inability to add custom styles, that is due to the missing style property on the base Element. That's probably due to the specification of the style attribute:
All HTML elements may have the style content attribute set. This is a style attribute as defined by the CSS Style Attributes specification.
HTML elements are:
To ease migration from HTML to XML, UAs conforming to this specification will place elements in HTML in the http://www.w3.org/1999/xhtml namespace, at least for the purposes of the DOM and CSS. The term "HTML elements" refers to any element in that namespace, even in XML documents.
However, style property exists in SVGElement, and probably some other base prototypes, so there must be some other specifications that allow that. But I thought that's out of scope of my original question.
And that concludes my research.

Is there a practical use for the additional DOM subcategories in Devtools > Elements > Properties?

Like everyone else I use Chrome DevTools to inspect an HTML Element's properties. For example if I needed to know which properties were attached to a specific <DIV> I would do this.
Go to DevTools
Open the Elements panel
Click the HTML DIV element I wanted to inspect
In the right panel click the Properties tab
The top listing will be div.(classname)
Click that label and view the properties
Awesome! I can see all of the properties attached to that node and use them as needed.
But below that are 6 additional listings that I and possibly a lot of other people never use. They appear to represent part of the DOM hierarchy.
HTMLDivElement
HTMLElement
Element
Node
EventTarget
Object
Question: Do these also have a practical use when building a site? Am I missing out on something cool that I could use them for? Are they merely there for reference? Thanks for any input!
You have a list of object and interface types and contrary to your assertion that not a lot of people use them. They are extensively used (although you may not even realize it).
Object
In JavaScript, everything is an Object. Objects are endowed with basic properties and methods and literally every other object inherits these.
EventTarget
Is specific reference to the object that was the source for an event being triggered.
Node
In the W3C Document Object Model API (nice overview here), specific element types are not what is paramount. All elements and attributes (as well as other types of markup, such as DOCTYPE and comments) are generically referred to as "nodes" and every node has certain properties (i.e. nodeName, nodeType, nodeValue and methods). The DOM API favors treating all markup as fundamental nodes. This API is designed this way because it works with HTML but also XML.
Element
Is a generic term used to talk about any HTML element.
HTMLElement
Is an "interface" that describes the various ways you can programatically interact with any object that implements the interface (as all HTML elements do).
HTMLDivElement
Is a more specific interface that describes what an HTML DIV element should expose for programattic interaction.
Don't get confused between tag names, like <div> and DOM interfaces such as 'HTMLDivElement`. The first is part of creating a document structure and the second is an interface for the browser and scripting.
The HTMLDivElement interface provides special properties (beyond the
regular HTMLElement interface it also has available to it by
inheritance) for manipulating div elements.
Search through MDN or the spec itself and carefully read those descriptions of the others in your list.

Angular 2 w3c validation [duplicate]

I've been unable to find a definitive answer to whether custom tags are valid in HTML5, like this:
<greeting>Hello!</greeting>
I've found nothing in the spec one way or the other:
http://dev.w3.org/html5/spec/single-page.html
And custom tags don't seem to validate with the W3C validator.
The Custom Elements specification is available in Chrome and Opera, and becoming available in other browsers. It provides a means to register custom elements in a formal manner.
Custom elements are new types of DOM elements that can be defined by
authors. Unlike decorators, which are stateless and ephemeral, custom
elements can encapsulate state and provide script interfaces.
Custom elements is a part of a larger W3 specification called Web Components, along with Templates, HTML Imports, and Shadow DOM.
Web Components enable Web application authors to define widgets with a
level of visual richness and interactivity not possible with CSS
alone, and ease of composition and reuse not possible with script
libraries today.
However, from this excellent walk through article on Google Developers about Custom Elements v1:
The name of a custom element must contain a dash (-). So <x-tags>, <my-element>, and <my-awesome-app> are all valid names, while <tabs> and <foo_bar> are not. This requirement is so the HTML parser can distinguish custom elements from regular elements. It also ensures forward compatibility when new tags are added to HTML.
Some Resources
Example Web Components are available at https://WebComponents.org
WebComponents.js serves as a polyfill for Web Components until they are supported everywhere. See also the WebComponents.js github page & web browser support table.
It's possible and allowed:
User agents must treat elements and attributes that they do not
understand as semantically neutral; leaving them in the DOM (for DOM
processors), and styling them according to CSS (for CSS processors),
but not inferring any meaning from them.
http://www.w3.org/TR/html5/infrastructure.html#extensibility-0
But, if you intend to add interactivity, you'll need to make your document invalid (but still fully functional) to accomodate IE's 7 and 8.
See http://blog.svidgen.com/2012/10/building-custom-xhtml5-tags.html (my blog)
Basic Custom Elements and Attributes
Custom elements and attributes are valid in HTML, provided that:
Element names are lowercase and begin with x-
Attribute names are lowercase and begin with data-
For example, <x-foo data-bar="gaz"/> or <br data-bar="gaz"/>.
A common convention for elements is x-foo; x-vendor-feature is recommended.
This handles most cases, since it's arguably rare that a developer would need all the power that comes with registering their elements. The syntax is also adequately valid and stable. A more detailed explanation is below.
Advanced Custom Elements and Attributes
As of 2014, there's a new, much-improved way to register custom elements and attributes. It won't work in older browsers such as IE 9 or Chrome/Firefox 20. But it allows you to use the standard HTMLElement interface, prevent collisions, use non-x-* and non-data-* names, and define custom behavior and syntax for the browser to respect. It requires a bit of fancy JavaScript, as detailed in the links below.
HTML5 Rocks - Defining New Elements in HTML
WebComponents.org - Introduction to Custom Elements
W3C - Web Components: Custom Elements
Regarding The Validity of The Basic Syntax
Using data-* for custom attribute names has been perfectly valid for some time, and even works with older versions of HTML.
W3C - HTML5: Extensibility
As for custom (unregistered) element names, the W3C strongly recommends against them, and considers them non-conforming. But browsers are required to support them, and x-* identifiers won't conflict with future HTML specs and x-vendor-feature identifiers won't conflict with other developers. A custom DTD can be used to work around any picky browsers.
Here are some relevant excerpts from the official docs:
"Applicable specifications MAY define new document content (e.g. a
foobar element) [...]. If the syntax and semantics of a given
conforming HTML5 document is unchanged by the use of applicable
specification(s), then that document remains a conforming HTML5
document."
"User agents must treat elements and attributes that they do not
understand as semantically neutral; leaving them in the DOM (for DOM
processors), and styling them according to CSS (for CSS processors),
but not inferring any meaning from them."
"User agents are not free to handle non-conformant documents as they
please; the processing model described in this specification applies
to implementations regardless of the conformity of the input
documents."
"The HTMLUnknownElement interface must be used for HTML elements that
are not defined by this specification."
W3C - HTML5: Conforming Documents
WhatWG - HTML Standard: DOM Elements
N.B. The answer below was correct when it was written in 2012. Since then, things have moved on a bit. The HTML spec now defines two types of custom elements - "autonomous custom elements" and "customized built-in elements". The former can go anywhere phrasing content is expected; which is most places inside body, but not e.g. children of ul or ol elements, or in table elements other than td, th or caption elements. The latter can go where-ever the element that they extend can go.
This is actually a consequence of the accumulation of the content model of the elements.
For example, the root element must be an html element.
The html element may only contain A head element followed by a body element.
The body element may only contain Flow content where flow content is defined as the elements: a,
abbr,
address,
area (if it is a descendant of a map element),
article,
aside,
audio,
b,
bdi,
bdo,
blockquote,
br,
button,
canvas,
cite,
code,
command,
datalist,
del,
details,
dfn,
div
dl,
em,
embed,
fieldset,
figure,
footer,
form,
h1,
h2,
h3,
h4,
h5,
h6,
header,
hgroup,
hr,
i,
iframe,
img,
input,
ins,
kbd,
keygen,
label,
map,
mark,
math,
menu,
meter,
nav,
noscript,
object,
ol,
output,
p,
pre,
progress,
q,
ruby,
s,
samp,
script,
section,
select,
small,
span,
strong,
style (if the scoped attribute is present),
sub,
sup,
svg,
table,
textarea,
time,
u,
ul,
var,
video,
wbr
and Text
and so on.
At no point does the content model say "you can put any elements you like in this one", which would be necessary for custom elements/tags.
I would like to point out that the word "valid" can have two different meanings in this context, either of which is potentially, um, valid.
Should an HTML document with custom tags be considered valid HTML5?
The answer to this is clearly "no." The spec lists exactly what tags are valid in what contexts. This is why an HTML validator will not accept a document with custom tags, or with standard tags in the wrong places (like an "img" tag in the header).
Will an HTML document with custom tags be parsed and rendered in a standard, clearly-defined way across browsers?
Here, perhaps surprisingly, the answer is "yes." Even though the document would not technically be considered valid HTML5, the HTML5 spec does specify exactly what browsers are supposed to do when they see a custom tag: in short, the custom tag acts kind of like a <span> - it means nothing and does nothing by default, but it can be styled by HTML and accessed by javascript.
To give an updated answer reflecting modern pages.
Custom tags are valid if either,
1) They contain a dash
<my-element>
2) They are embedded XML
<greeting xmlns="http://example.com/customNamespace">Hello!</greeting>
This assumes you are using the HTML5 doctype <!doctype html>
Considering these simple restrictions it now makes sense to do your best to keep your HTML markup valid (please stop closing tags like <img> and <hr>, it's silly and incorrect unless you use an XHTML doctype, which you probably have no need for).
Given that HTML5 clearly defines the parsing rules a compliant browser will be able to handle any tag that you throw at it even if it isn't strictly valid.
Custom HTML elements are an emerging W3 standard I have been contributing to that enables you to declare and register custom elements with the parser, you can read the spec here: W3 Web Components Custom Elements spec. Additionally, Microsoft supports a library (written by former Mozilla devs), called X-Tag - it makes working with Web Components even easier.
Quoting from the Extensibility section of the HTML5 specification:
For markup-level features that can be limited to the XML serialization and need not be supported in the HTML serialization, vendors should use the namespace mechanism to define custom namespaces in which the non-standard elements and attributes are supported.
So if you're using the XML serialization of HTML5, its legal for you to do something like this:
<greeting xmlns="http://example.com/customNamespace">Hello!</greeting>
However, if you're using the HTML syntax you are much more limited in what you can do.
For markup-level features that are intended for use with the HTML syntax, extensions should be limited to new attributes of the form "x-vendor-feature" [...] New element names should not be created.
But those instructions are primarily directed at browser vendors, who would assumedly be providing visual styling and functionality for whatever custom elements they chose to create.
For an author, though, while it may be legal to embed a custom element in the page (at least in the XML serialization), you're not going to get anything more than a node in the DOM. If you want your custom element to actually do something, or be rendered in some special way, you should be looking at the Custom Elements specification.
For a more gentle primer on the subject, read the Web Components Introduction, which also includes information about the Shadow DOM and other related specifications. These specs are still working drafts at the moment - you can see the current status here - but they are being actively developed.
As an example, a simple definition for a greeting element might look something like this:
<element name="greeting">
<template>
<style scoped>
span { color:gray; }
</style>
<span>Simon says:</span>
<q><content/></q>
</template>
</element>
This tells the browser to render the element content in quotes, and prefixed by the text "Simon says:" which is styled with the color gray. Typically a custom element definition like this would be stored in a separate html file that you would import with a link.
<link rel="import" href="greeting-definition.html" />
Although you can also include it inline if you want.
I've created a working demonstration of the above definition using the Polymer polyfill library which you can see here. Note that this is using an old version of the Polymer library - more recent versions work quite differently. However, with the spec still in development, this is not something I would recommend using in production code anyway.
just use whatever you want without any dom declaration
<container>content here</container>
add your own style (display:block) and it will work with any modern browser
data-* attributes are valid in HTML5 and even in HTML4 all web browsers used to respect them.
Adding new tags is technically okay, but is not recommended just because:
It may conflict with something added in the future, and
Makes the HTML document invalid unless dynamically added via JavaScript.
I use custom tags only in places that Google does not care, for ecample in a game engine iframe, i made a <log> tag that contained <msg>, <error> and <warning> - but through JavaScript only. And it was fully valid, according to the validator. It even works in Internet explorer with its styling! ;]
Custom tags are not valid in HTML5. But currently browsers are supporting to parse them and also you can use them using css. So if you want to use custom tags for current browsers then you can. But the support may be taken away once the browsers implement W3C standards strictly for parsing the HTML content.
I know this question is old, but I have been studying this subject and though some of the above statements are correct, they aren't the only way to create custom elements. For example:
<button id="find">click me</button>
<Query? ?attach="find" ?content="alert( find() );" ?prov="Hello there :D" >
I won't be displayed :D
</Query?>
<style type="text/css">
[\?content] {
display: none;
}
</style>
<script type="text/javascript">
S = document.getElementsByTagName("Query?")[0];
Q = S.getAttribute("?content");
A = document.getElementById( S.getAttribute("?attach") );
function find() {
return S.getAttribute("?prov");
}
(function() {
A.setAttribute("onclick", Q);
})();
</script>
would work perfectly fine ( in newer versions of Google Chrome, IE, FireFox, and mobile Safari so far ). All you need is just an alpha character (a-z, A-Z) to start the tag, and then you can use any of the non alpha characters after. If in CSS, you must use the "\" (backslash) in order to find the element, such as would need Query\^ { ... } . But in JS, you just call it how you see it. I hope this helps out. See example here
-Mink CBOS

jQuery with an SVG document

jQuery is designed to be used in HTML pages with JavaScript.
SVG uses the same DOM Level 2 as HTML but is XML-based and specifies ECMAScript.
What problems could result from using jQuery with SVG? Would it be preferable to embed such SVG as an element in an HTML document?
Note, I'm not referring to the "jQuery SVG" drawing library which provides for manipulation of an SVG element in an HTML document as a graphics port using jQuery syntax. What I want is to use jQuery selectors and event management on SVG elements, with the SVG root maybe being inside HTML or maybe not.
Trying it out, selectors seem to work but other things don't. The $( function() { } ) idiom to initialize the page doesn't work because SVG only passes an SVGLoad event to the top <svg> element. $('svg').bind('SVGLoad', function(){}) does work, though.
Dynamically adding elements with .append puts them in the DOM such that they don't get rendered, at least on Firefox. The phantom elements remain invisible even after the document is re-rendered including an element dynamically added without jQuery. $().attr(key, value) may change an attribute but not update the onscreen display.
It all seems unfortunately broken. More features work once it's embedded in an XHTML document. But defects such as the above remain and it's probably better to use another framework. Maybe give jQuery SVG another look…

Local id-s for HTML elements

I am developing a kind of HTML+JS control which can be embedded into various web pages. I know nothing about those pages (well, I could, but I don't want to). The control consists of one root element (e.g. DIV) which contains a subtree of child elements. In my script, I need to access the child elements. The question is: how can I mark those child elements to distinguish them?
The straightforward solution is using id-s. The problem here is that the id must be unique in the scope of the entire document, and I know nothing about the document my control will be embedded into. So I can't guarantee the uniqueness of my id-s. If the id-s are not unique, it will work (if used with care), but this does not conform with the standard, so I can meet problems with some new versions of the browsers, for example.
Another solution is to use the "name" attribute. It's not required to be unique -- that's good. But again, the standard allows the presence of "name" attribute only for a restricted set of element types. For example, the "name" attribute is invalid for DIV elements.
I could use, for example, the "class" attribute. It seems to be OK with the standards, but it's not OK with the meaning. "class" should be used for other purposes, and this may be confusing.
Can anybody suggest some other options to implement local id-s for HTLM elements?
You could use the HTML5 data-* attributes so you can give them a custom name with the right meaning:
https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes
Do something like:
<div id="element-id" data-local-id="id-value">
...
</div>
and get the value in JavaScript with:
const el = document.getElementById('element-id');
const { localId } = el.dataset;
If you use a prefix to all of your ID's and or classes such as myWidgetName_98345699- the likelihood of collisions is highly improbable.
<div id="myWidgetName_98345699-container" class="myWidgetName_98345699-container">
jQuery does have selectors that will search for part of an ID, so using common names like container would be smart to stay away from as well. Using a longish alphanumeric mix for the specific part of the ID would be smart also
Typically, including hidden information within the web page required creative approaches. For example:
Storing information within HTML element attributes such as id, class, rel, and title, thus overriding the attributes original intent.
Using <span> or <div> blocks that contain the information, while making such blocks invisible to the user through styling (style="display: none;").
Adding JavaScript code to the web page to define data structures that map to HTML ID elements.
Adding your own attributes to existing HTML elements (breaking the HTML standard itself, and relying on the HTML browser to ignore any syntax errors).
The approaches above are not elegant and are not good coding practice, but the good news is that jQuery has a facility that simplifies associating data to DOM elements in a clean, cross-browser manner.
Use the custom data attributes:
Any attribute that starts with "data-" will be treated as a storage area for private data (private in the sense that the end user can't see it - it doesn't affect layout or presentation.
Defining custom data via html:
<div class="bar" id="baz" data-id="foo">
...
</div>
Associating data-id to specific DOM elements (jQuery):
$('#foo').data('id', 'baz');
Retrieving an element with specific data-id:
var $item = $('*[data-id="baz"]');

Categories

Resources