Is an element attribute a node or not? - javascript

According to http://www.w3schools.com/js/js_htmldom_navigation.asp tutorial, element attributes are also nodes. In the example below, script is showing only element nodes.
<!DOCTYPE html>
<html>
<body>
link
<p id="demo"></p>
<script>
var n = document.body.childNodes;
var s = "";
for (var i = 0; i < n.length; i++)
s += n[i].nodeName + "<br>";
document.getElementById("demo").innerHTML = s;
</script>
some text
</body>
</html>
The result (node names) is:
#text
A
#text
P
#text
SCRIPT
I guess #text is node name for line breaks etc (but I have no idea why text after SCRIPT is not shown as #text).
Why it's not showing href attribute? Even when I try to see all child nodes of anchor element, it's showing only text node inside.

tl;dr: Yes, they are nodes, but they are treated differently.
From the DOM spec:
Attr objects inherit the Node interface, but since they are not actually child nodes of the element they describe, the DOM does not consider them part of the document tree. Thus, the Node attributes parentNode, previousSibling, and nextSibling have a null value for Attr objects. The DOM takes the view that attributes are properties of elements rather than having a separate identity from the elements they are associated with; this should make it more efficient to implement such features as default attributes associated with all elements of a given type. Furthermore, Attr nodes may not be immediate children of a DocumentFragment. However, they can be associated with Element nodes contained within a DocumentFragment. In short, users and implementors of the DOM need to be aware that Attr nodes have some things in common with other objects inheriting the Node interface, but they also are quite distinct.
As the text says, attribute nodes are not considered to be children of the element, hence they are not contained in childNodes. To get the attributes of an element, you can access element.attributes.

Element attributes are not nodes.
If you check MDN about .childNodes (wich is a far better source that w3schools) you will read:
The Node.childNodes read-only property returns a live collection of child nodes of the given element.
In the DOM3 spec one can read:
Attr objects inherit the Node interface, but since they are not actually child nodes of the element they describe, the DOM does not consider them part of the document tree.
About your other question, the reason why you do not see the text after the <script>tag is because the DOM is not ready loaded yet. If you put that code in the end, near </body>, then everything will be there.

Related

Isn't text node a child when using children function?

I have the following html code:
<h1>
When
<!-- Green highlight effect -->
<span class="highlight">banking</span>
meets<br />
<span class="highlight">minimalist</span>
</h1>
And i wrote the following code in js:
const h1 = document.querySelector('h1');
// Going downwards: child
console.log(h1.childNodes); //prints text element(**When**)
console.log(h1.children); // doesn't print text element (**When**)
i understand that children function prints only direct child, but As far as i understand, When is indeed direct child of h1.
Can someone explain me if i'm wrong?
Isn't text node a child when using children function?
Yes. Text nodes are nodes and can be child nodes of an element.
doesn't print text element
There's no such thing as a text element (at least in HTML, SVG has one). Element nodes and text nodes are different kinds of nodes.
You're reading too much into the name of the property.
See the MDN documentation:
children is a read-only property that returns a live HTMLCollection which contains all of the child elements
or the specification:
The children attribute’s getter must return an HTMLCollection collection rooted at this matching only element children.
If you want to get all the nodes, including the text nodes, then use childNodes. DOM doesn't need two properties that do the same thing and it is often useful to get just the elements (especially if the only text nodes contain only white space).

In mdn web docs Element.querySelector method says that it should be descendant but example shows otherwise

I am learning JavaScript from the MDN web docs. I was studying Element.querySelector() method.
It is written that it returns the first element that is a descendant of the element on which it is invoked that matches the specified group of selectors.
But there is an example given, which contradicts this fact.
var baseElement = document.querySelector("p");
document.getElementById("output").innerHTML =
(baseElement.querySelector("div span").innerHTML);
<div>
<h5>Original content</h5>
<p>
inside paragraph
<span>inside span</span>
inside paragraph
</p>
</div>
<div>
<h5>Output</h5>
<div id="output"></div>
</div>
Here, div tag is not a descendant of p tag, still this code works.
Can you point where I am going wrong ?
Element.querySelector() first applies the CSS Selectors passed to .querySelector() method, on the whole document and not the base element on which .querySelector() was invoked. This is done to generate initial set of potential elements.
After generating initial set of potential elements, list of potential elements is then filtered to retain only those elements which are descendants of the base element. Finally, the first element from this filtered list is returned.
In your code example, entire document is first searched for elements that match div span. As there is only one element in the entire document that matches div span selector, initial set of potential elements contains only one span element. After that, this span element is checked to see if it is the descendant of baseElement. Since, in this case, it is a descendant of
the baseElement, it is returned.
What i explained above is written under "Return Value" heading in MDN - Element.querySelector()
The entire hierarchy of elements is
considered when matching, including those outside the set of elements
including baseElement and its descendants; in other words, selectors
is first applied to the whole document, not the baseElement, to
generate an initial list of potential elements. The resulting elements
are then examined to see if they are descendants of baseElement. The
first match of those remaining elements is returned by the
querySelector() method.

Javascript node empty even before appending it's contents to a different node

I'm creating a JQuery object(let's call it $dummyHTML) and setting some html content inside it. Then I go through each of it's child nodes including text ones, do some checks, and append them to a new different JQuery Object(let's call it $refinedHTML).
But the problem is that the contents of $dummyHTML seems to be empty even before I append them to $refinedHTML!
Now, I know that JQuery append function doesn't copy a node, it actually transfers the node to the other JQuery object. So I'm guessing the append function triggers before I mean it to?
Here is a minified example of the issue.
var $dummyHTML = $('<div/>');
$dummyHTML.html('Hello there, <span>myself!</span>');
var $refinedHTML = $('<div/>');
console.log($dummyHTML[0]);
$dummyHTML.contents().each(function() {
$refinedHTML.append($(this));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
But if I remove the .contents part the programs works as expected.
.contents() extracts the content of a DOM element .When you create an object on the fly,it is not yet a DOM element so .contents() will not work however you can manipulate the object data in other ways.
Reference here:
Given a jQuery object that represents a set of DOM elements, the .contents() method allows us to search through the immediate children of these elements in the DOM tree and construct a new jQuery object from the matching elements.

Get the first body tag in a document with multiple bodies

I have a html document containing an inline SVG with some <foreignObject>s in it. Those all have an own <body> tag.
Now I want to find the top <body>.
A simple solution would be
document.getElementsByTagName("body")[0]
but this seems to be inefficient (because it would first select all bodies and then drop all but the first) and I'm not quite sure if it's really reliable (is the ordering in such a set actually defined or may this change with other/newer browsers?)
Can see someone another way which is both efficient and reliable?
Your HTML document doesn't actually have multiple bodies as you allude to in the title, despite what the presence of body elements within the foreignObject elements might suggest.
Your HTML document still has only one body, its own body element, of which the foreignObject elements are descendants. This is always represented by document.body.
According to the documentation, getElementsByTagName:
Returns a NodeList of all the Elements with a given tag name in the order in which they would be encountered in a preorder traversal of the Document tree.
So, "is the ordering in such a set actually defined?". Yes, it returns the elements in the order they appear in the tree structure.
Reference: https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#method-getElementsByTagName
You can use document.body element which returns the <body> element.
if you need the <html> element then the documenut.documentElement can be used

html element - property of document object ? or an object?

so, html elements such as <title>are sometimes referred as property, but sometimes they are referred as objects. i am kinda confused. are html elements properties of document object? or are they objects? or are they both at the same time? thanks. to make question meet quality standards i will add some random codes.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
The document itself is a document node.
All HTML elements are element nodes.
All HTML attributes are attribute nodes.
Text inside HTML elements are text nodes.
Comments are comment nodes.
In the HTML DOM, the Element object represents an HTML element.
DOM w3schools
The document object has a title property, which is a string, which is an object. But the document object does not have direct properties for the html elements in the page, that's why you have accessor functions like document.getElementById('id'), which return objects representing html elements. Open up a console in chrome and type document. to see all the properties the document object has. Also see that document.title and document.getElementByTagName('title')[0] do not return the same thing.
The DOM, or Document Object Model is a tree. The HTML document available at window.document is the root node of this tree.
Essentially everything else in the document is a node somewhere in this tree, whether it is an element like <p> or an attribute node like class="foo" or a text node. Each of these nodes are objects that you can interact with via Javascript.
They are two separate things.
Element is the HTML element or tag.
Javascript and jQuery (which is also Javascript), for example, modify and control the HTML elements by using the HTML DOM (HTML Document Object Model). The DOM contains the Objects you're referring to. Each DOM object refers to an element and when the Javascript modifies your HTML page, it's actually accessing the DOM, not the HTML elements.
Take a look at: http://www.w3.org/TR/DOM-Level-2-Core/introduction.html.

Categories

Resources