When are nodes added to elements by the browser? - javascript

Nodes are 'automagically' added to elements by Chrome. More experienced front end devs probably deal with this frequently.
It was surprising for me to find in Chrome that the nested div e2 <div id="e1"><div id="e2"></div></div> has NodeList [] well ok, that is expected, but div e1 has
NodeList(3) [text, div#e2, text] !!
So an empty div has no child nodes while the outer of two nested divs has 3 child nodes. I can see that text could be added between the divs, so the two text nodes maybe act as placeholders.
But I'm wondering where can I find documentation for this behaviour? What's it called anyway?
And by the same auto add logic shouldn't the inner div have a placeholder text node too??

It is how the method treats whitespace.
childNodes: includes all child nodes—including non-element nodes like text and comment nodes.
const test = elem => console.log(elem.id, elem.childNodes.length, elem.children.length);
test(document.querySelector("#test1"));
test(document.querySelector("#test2"));
test(document.querySelector("#test3"));
test(document.querySelector("#test4"));
<div id="test1"></div>
<div id="test2"> </div>
<div id="test3"><div></div></div>
<div id="test4">
<div></div>
</div>

Related

how does childNode indexing work with javascript?

For example, if I have
<div>
<h2>Name</h2>
<h3>age</h3>
<span class='fa fa-trash'></span>
</div>
and when clicking the span (icon) I say
this.parentNode.childNodes[1].innerText
it would target the Name but if I say
this.parentNode.childNodes[2].innerText
it would not target Age. why is this? Is there a resource that explains this well? I know the indexing doesn't start at 0 but I don't understand how the indexing work.
DOM is not just the elements you see in your HTML code. In-between each element is a "text node" where text can be displayed. An example of this would be having text in a div below a a header. So...
<div>
<!-- Index 0: Text node -->
<h1>Header Text</h1> <!-- Index 1: Element -->
Description Text <!-- Index 2: Text node -->
</div>
As you can see, you are allowed to insert text in the div without wrapping it in an element. These are called text nodes which you see when you put the text in normal text elements (such as span or p) or buttons (<button>TEXT</button>). So to get around this in you JavaScript code, you could either do it the lazy way;
document.getElementById("ELEMENT_ID").childNodes[INDEX*2 + 1]
or by using the children property;
document.getElementById("ELEMENT_ID").children[INDEX]
The problem with this method is that it only returns 'element' children within the div, so the description text in the above HTML example will not be accessible. ([H1] instead of [Text, H1, Text]), but I suppose that is what you're looking for anyway. :)

Is it possible to delete a certain type of child element?

I am trying to make a simple website that has to do with surveys (like making surveys, posting them, answering them, seeing responses, etc), but I have a problem that would take a lot of code to solve, and involve hardcoding. I am trying to delete all the br child elements from a div parent element in one shot, so like one line of code or two lines max.
As you can see, there are a lot of br tags in that parent div. I want a single line or double line of code that can delete all those br tags in one shot. So in the end it should look like this:
Thank you!
You'll need to iterate your parent node's children, then you can use element.parentNode.removeChild(element) when a condition applies:
const parentElement = document.getElementById('parent');
[...parentElement.children].forEach((element) => {
if (element.tagName === 'BR') {
element.parentNode.removeChild(element);
}
});
<div id="parent">
<div>foo</div>
<br>
<br>
<br>
<span>bar</span>
<br>
<br>
<br>
<div>baz</div>
</div>
Note that you can't iterate the HTML property children (similarly to classList). The trick to do that is to simply spread it (i.e. [...foo])

Why one DIV has only one child but has three child nodes?

I have two divs looks like:
<div id="responseframe">
<div id="oldframe">
</div>
</div>
I thought the #oldframe DIV is the only child of #responseframe. However, when I write this in javascript,
var old=document.getElementById("responseframe");
var nodesnumber=old.childNodes.length;
console.log("-------------Here is the nodes number of reponseframe---------: "+nodesnumber);
var nodesname=old.childNodes[i].nodeName;
console.log("-------------Here is the nodes name of reponseframe's child---------: "+nodesname);
console told me #responseframe has 3 child nodes and,
childNode[0] is #text;
childNode[1] is DIV ;
childNode[2] is #text
Why there are 2 #text? Thank you for any idea.
Because of you added new line after <div id="responseframe"> and after first </div>.
If you put this in one line will be there is one node: div.
Html:
<div id="responseframe"><div id="oldframe"></div></div>
Output:
-------------Here is the nodes number of reponseframe---------: 1
-------------Here is the nodes name of reponseframe's child---------: DIV
Here is fiddle: http://jsfiddle.net/cassln/t7kec97u/2/
Node.childNodes property returns all direct child elementNodes of parent element including textNodes, commentNodes.
So in your case you have:
<div id="responseframe"><!-- this whole space area is considered by html as single space so you got your first #text Node
--><div id="oldframe"><!-- this area is ignored because this is not direct child area of the responseframe
--></div><!-- this whole space area is considered by html as single space so you got your second #text Node
--></div>
So finally we got direct children: #text0 #DIV(oldframe) #text1.
If you want to get only direct elementNode (without textNodes and commentNodes) you need Node.children.
var old=document.getElementById("responseframe");
var nodesnumber=old.children.length;
console.log("-------------Here is the nodes number of reponseframe---------: "+nodesnumber);
var nodesname=old.children[i].nodeName;
console.log("-------------Here is the nodes name of reponseframe's child---------: "+nodesname);

How to select a DIV if its child has any children?

I'm trying to select any divs on a page if a certain child of theirs has any children of its own.
Here's how the structure looks:
<div id="ID-SOME_LONG_ID">
<div class="GK">
<div id="SOME_LONGID_#1434646398866197"></div>
</div>
</div>
So I want to select all divs with id ID-SOME_LONG_ID only if the GK DIV has any children. It may or may not.
ID- stays the same and SOME_LONG_ID changes with each one.
The other one SOME_LONG_ID is the same on as the parent, and after the # it's a 16 digit number that is random.
Would using Regex be a good idea to look for them or maybe using jQuery's .children() like $( ".GK" ).children()?
Thank you!
Use :has(), :empty, and :not()
$('#ID-SOME_LONG_ID:has(.GK:not(:empty))')
However, note, :empty will fail if you want real children without text nodes. In that case you can do
$('.GK').filter(function() {
return $(this).children().length > 0;
});

Appending a div on unknodw div

I have three divs. How should I append a div onto an unknown div?
<div class="main" >
<div id="drag-box" >
<div id="" class=""> </div>
</div>
</div>
I want to append div on an unknown div which is come after drag-box div. I don't know which div comes after drag-box div. But there must be one div after drag-box div.
$("#drag-box div:first-child").append("<span />");
or
$("#drag-box div").first().prepend("<span>first</span>");
For a complete answers, here it is working:
http://jsfiddle.net/dMUD3/
try this
$("#drag-box div:first-child").attr("id");
Instead of giving you a one liner I would like to give you an indepth solution.
A browser takes your html and parses what is called a DOM Tree out of it.
so if your html is .
<div class="a">
<div class="foo"></div>
<button class="foogle"></button>
</div>
The tree structure will become something like
`-div.a
|-div.foo
`Button.foogle
You should actually look into DOM Api's at MDN
How DOM helps ?
With DOM api's you can actually access the unknown div using the reference to a known div. So if you actually understand your markup and its representation in DOM it should be pretty simple to get reference to nth child of an element;
You can access the child elements by the children attribute.
So
// Get reference to the element.
var parent = document.getElementById("drag-box");
// Use the dom.
var child_i_want = parent.children[0];
// or there is another way
var child_i_reallyWant = parent.firstElementChild;
There are solutions with jQuery but I feel its important for you to Understand basics of DOM even when there are helpful abstraction libraries in existance.
You'll need the + selector. It applies to the object directly following. See here.
.drag-box + div {
}
$('<div></div>').appendTo($('#drag-box div:first'))

Categories