childNode unexpected behaviour - javascript

Scenario
I would like to get all child nodes of my div and change it color.
Code:
function myFunction() {
var divv = document.getElementById("divv");
var myCollection = divv.childNodes;
var len = myCollection.length;
var i;
for (i = 0; i < len; i++) {
myCollection[i].style.color = "red";
}
}
<div id="divv">
<h2>JavaScript HTML DOM</h2>
<p>Hello World!</p>
<p>Hello Norway!</p>
<p>Click the button to change the color of all p elements.</p>
<button onclick="myFunction()">Try it</button>
</div>
Error:
This is not working. It seems tha in my collection i have all nodes. h2 p text buton. I Expeceted just p h2 and buton.
EDIT
Explanation
Note: Whitespace inside elements is considered as text, and text is considered as nodes. Comments are also considered as nodes.
So we need to check if node is element node, or use querySelectorAll.
Examples in answers below. Thanks for your help.

Text nodes do not have style attributes. If you want to use childNodes, check that the nodeType is 1 (an Element node) first:
function myFunction() {
var divv = document.getElementById("divv");
var myCollection = divv.childNodes;
var len = myCollection.length;
var i;
for (i = 0; i < len; i++) {
if (myCollection[i].nodeType === 1) myCollection[i].style.color = "red";
}
}
<div id="divv">
<h2>JavaScript HTML DOM</h2>
<p>Hello World!</p>
<p>Hello Norway!</p>
<p>Click the button to change the color of all p elements.</p>
<button onclick="myFunction()">Try it</button>
</div>
But I would prefer using querySelectorAll and forEach here:
function myFunction() {
document.querySelectorAll('#divv > *')
.forEach(child => child.style.color = "red");
}
<div id="divv">
<h2>JavaScript HTML DOM</h2>
<p>Hello World!</p>
<p>Hello Norway!</p>
<p>Click the button to change the color of all p elements.</p>
<button onclick="myFunction()">Try it</button>
</div>
(or, you could simply set #divv's style.color to red)

You could use the children property to access the children of a given node:
The ParentNode property children is a read-only property that returns a live HTMLCollection which contains all of the child elements of the node upon which it was called.
- MDN web docs
function myFunction() {
var divv = document.getElementById("divv");
var myCollection = divv.children;
var len = myCollection.length;
var i;
for (i = 0; i < len; i++) {
myCollection[i].style.color = "red";
}
}
<div id="divv">
<h2>JavaScript HTML DOM</h2>
<p>Hello World!</p>
<p>Hello Norway!</p>
<p>Click the button to change the color of all p elements.</p>
<button onclick="myFunction()">Try it</button>
</div>
Another way to do with ES6 would be to spread the child nodes into an array and loop through them with a .forEach:
const myFunction = () => {
[...document.querySelector('#divv').children].forEach(child => {
child.style.color = 'red';
});
}
<div id="divv">
<div class="child">
I am a child
</div>
<div>
<div class="grandchild">
I am a grand child
</div>
</div>
<button onclick="myFunction()">Try it</button>
</div>
Alternatively, you could use the .forEach from the NodeList class directly but the previous method gives you more freedom to work with Array's method such as .reduce, .map, etc...
const myFunction = () => {
document.querySelectorAll('#divv > *').forEach(child => {
child.style.color = 'red';
});
}
<div id="divv">
<div class="child">
I am a child
</div>
<div>
<div class="grandchild">
I am a grand child
</div>
</div>
<button onclick="myFunction()">Try it</button>
</div>

Related

change the text of every element in a class javascript

How do I change the text of all elements in a class
If the element is in a division do I need to do anything else?
P.S. I hardly know js so plz help.
enter image description here
You can use querySelectorAll and with a foreach set the new text:
const examples = document.querySelectorAll('.example');
examples.forEach(example => {
example.innerHTML = 'new text';
});
<div class="example">
text 1
</div>
<div class="example">
text 2
</div>
I hope these examples can help you
function myFunction()
{
x=document.getElementsByClassName("infoblock"); // Find the elements
for(var i = 0; i < x.length; i++){
x[i].innerText="text changed!"; // Change the content
}
}
function myFunction2()
{
x=document.getElementsByClassName("notationgrade"); // Find the first span elements
y=document.getElementsByClassName("percentgrade"); // Find the second span elements
for(var i = 0; i < x.length; i++){
x[i].innerText="text 1 changed!"; // Change the content
}
for(var i = 0; i < y.length; i++){
y[i].innerText="text 2 changed!"; // Change the content
}
}
<body>
<div class="class-stats fsClassStatsAverage">
<p><span class="infoblock notationgrade">old text 1 </span></p>
<p> <span class="infoblock percentgrade">old text 2</span></p>
</div>
<button type="button" onclick="myFunction()">Change All Spans</button>
<button type="button" onclick="myFunction2()">Change Each Span</button>
</body>

can't change "class" by using attr()

var allp = $("div p");
for (var i = 0; i < allp.length; i++) {
allp.attr("class", function(i, n) {
n += 1;
return n;
});
console.log(allp[i]);
}
<script src="https://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
<div>
<p class="1">1</p>
<p class="2">2</p>
<p class="3">3</p>
<p class="4">4</p>
<p class="5">5</p>
</div>
i means index, n means the current value of "class". Just wanted to make each classname +1,but failed to do that.And the console.log is :
<p class="11111">1</p>
<p class="21111">2</p>
<p class="31111">3</p>
<p class="41111">4</p>
<p class="51111">5</p>
Expected output:
<p class="2">1</p>
<p class="3">2</p>
<p class="4">3</p>
<p class="5">4</p>
<p class="6">5</p>
Simply ignore for loop:
var allp=$("div p");
allp.attr("class",(i,n)=>Number(n)+1);
console.log(allp)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p class="1">1</p>
<p class="2">2</p>
<p class="3">3</p>
<p class="4">4</p>
<p class="5">5</p>
</div>
Maybe:
var allp = $("div p");
for (var i = 0; i < allp.length; i++) {
allp.attr("class", function (i, n) {
const n2 = Number(n) + 1;
return n2;
});
console.log(allp[i]);
}
You just need to get the class attribute value of each p element increment it after converting it to a Number and then assign this value to the same element as the new text value.
var allp=$("div p");
for(var i=0;i<allp.length;i++){
$(allp[i]).text(Number($(allp[i]).attr("class")) + 1);
console.log(allp[i]);
}
<script src="https://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
<div>
<p class="1">1</p>
<p class="2">2</p>
<p class="3">3</p>
<p class="4">4</p>
<p class="5">5</p>
</div>
Use jQuery.each() to iterate through each element in $allp, then .attr() to set the new class name.
var $allp = $("div p")
$.each($allp, (index, el) => {
const $newEl = $(el).attr('class', `newClass-${index + 2}`)
console.log($newEl[0])
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div>
<p class="1">1</p>
<p class="2">2</p>
<p class="3">3</p>
<p class="4">4</p>
<p class="5">5</p>
</div>
Codepen
You can use jquery. Get the class, parse it to int and increment. It'll throw an error if you have none numeric characters in your class though so may want to do a check !isNaN.
$('div p').each(function(){
console.log(parseInt($(this).attr('class')) + 1);
});

Javascript replace parent html (remove child)

I would like loop each iframes tags I've on my page and replace them all with a new div and on the way delete also the parent content so the new div will be the only child:
<div id="parent">
<p>this is parent content</p>
<iframe src="http://www.example.com" id="iframe10"></iframe>
</div>
Result should be:
<div id="parent">
<div id="newdiv">this is new div</div>
</div>
Here is my code for looping all iframes on page, the problem I don't understand how I can access each iframe parent and delete its contents:
var i, frames;
frames = document.getElementsByTagName("iframe");
for (i = 0; i < frames.length; ++i)
{
frame_id = frames[i].id;
}
Thanks
Shai
you can write it as following:
function remove_frames() {
var i = 0;
var frames = document.getElementsByTagName("iframe");
while (frames.length > 0) {
var f = frames[0];
var p = f.parentElement;
if (p) {
while (p.children.length > 0) {
p.children[0].remove();
}
p.innerHTML = "<div id=\"newdiv" + i + "\">this is new div" + i + "</div>";
i++; //increase id index
//p.appendChild(
}
}
}
<p><input type="button" value="Execute" onclick="remove_frames()" /></p>
<div id="parent">
<p>this is parent content</p>
<iframe src="http://www.example.com" id="iframe10"></iframe>
</div>
<p style="color:#6595ee">This element does not contain any sibling IFrame and must be exist in final result!</p>
<div id="parent2">
<p>this is parent2 content...</p>
<div>another element</div>
<iframe src="http://www.example.com" id="iframe20"></iframe>
<p>another element after iframe.</p>
</div>
var i, frames;
frames = document.getElementsByTagName("iframe");
for (i = frames.length; i; --i) // the array-like object shrinks every time a frame is removed so we have to loop backwards
{
//frame_id = frames[i].id;
// get the parent element
var parent = frames[i].parentElement;
// empty it (remove all it's elements)
while(parent.firstChild)
parent.removeChild(parent.firstChild);
// add the new div
var div = /* create new div */;
parent.appendChild(div);
}
You could use the parentElement
var iframes = document.getElementsByTagName("iframe");
iframes[0].parentElement.innerHTML = `<div id="newdiv">this is new div</div>`;
<div id="parent">
<p>this is parent content</p>
<iframe src="http://www.example.com" id="iframe10"></iframe>
</div>
You can use Node.parentNode to get the parent and Node.removeChild or Element.innerHTML to delete the content.
var i, frames;
frames = document.getElementsByTagName("iframe");
for (i = frames.length-1; i >=0; i--) {
var frame = frames[i];
if (frame.parentNode) {
var parent = frame.parentNode;
while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}
}
}
<div id="parent">
<p>this is parent content</p>
<iframe src="http://www.example.com" id="iframe10"></iframe>
</div>

javascript onclick get the div id?

Is it possible to get the ids of the 2 div tags on clicking the button, using javascript?
<div id="main">
<div id="content">
</div>
<button onclick="function();">show it</button>
</div>
I have 2 div tags here. The 1st div is in the main div while the content div is inside the main div and the button is inside the main div as well.
Is it possible to get the main and content id of the 2 div tags on clicking the button?
EXPECTED OUTPUT when I press the button:
alert: main
alert: content
You need to pass the element to the function. Then you can use parentNode to get the DIV that contains the button. From there, you can use querySelector to find the first DIV in the parent.
function showIt(element) {
var parent = element.parentNode;
alert(parent.id);
var content = parent.querySelector("div");
alert(content.id);
}
<div id="main">
<div id="content">
</div>
<button onclick="showIt(this);">show it</button>
</div>
<div id="main2">
<div id="content2">
</div>
<button onclick="showIt(this);">show it</button>
</div>
<div id="main3">
<div id="content3">
</div>
<button onclick="showIt(this);">show it</button>
</div>
document.getElementById('button').onclick = function () {
var divs = document.querySelectorAll('div');
for (var i = 0; i < divs.length; i++) {
var id = divs[i].getAttribute('id');
alert(id);
}
};
http://jsfiddle.net/jm5okh69/1/
This should work in all browsers and uses the cleaner .id method.
var button = document.getElementById('button');
button.onclick = getIDs;
function getIDs(){
var id,divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
id = divs[i].id // .id is a method
alert(id);
}
}
<div id="main">
<div id="content"></div>
<button id="button">show it</button>
</div>

How can I loop through all of the P tags and then write their innerHTML to the document at the end of the page?

I want to loop through all of the p tags on my web page and then write them to the end of the web page. I thought that this for loop would work but so far it is giving me an error.
How would I be able to do this and then append the text that is in the tag to the end of the page?
function forLoopTest() {
var i; //indexing tag for looping through all of the array elements
//for loop to loop through the pp array starting at index of zero
for (i = 0; i < pp.length;i++)
{
document.writeln("<br>" + pp[i].innerHTML); //write to the end of the page of each element
}
}
HTML Code:
<!DOCTYPE html>
<html>
<body>
<div id="main">
<p id="AA">A</p>
<p id="BB">B</p>
<p id="CC">C</p>
<p id="DD">D</p>
<p id="EE">E</p>
</div>
<p id="demo"></p>
<script>
var x = document.getElementById("main");
var pp = x.getElementsByTagName("p"); //creates an array of p elements
document.getElementById("demo").innerHTML = 'The first paragraph inside "main" is ' + pp[1].innerHTML;
function forLoopTest() {
var i;
for (i = 0; i < pp.length;i++) {
document.writeln("<br>" + pp[i].innerHTML;
}
}
forLoopTest();
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<div id="main">
<div id="main">
<p id="AA">A</p>
<p id="BB">B</p>
<p id="CC">C</p>
<p id="DD">D</p>
<p id="EE">E</p>
</div>
<p id="demo"></p>
<p style="color:blue;margin-left:20px;">This is a paragraph.</p>
<p id="A">A</p>
<p id="B">B</p>
<p id="C">C</p>
<p id="D">D</p>
<p id="E">E</p>
<div>Test</div>
</div>
<p id="demo"></p>
<script>
var x = document.getElementById("main");
var pp = x.getElementsByTagName("p"); //creates an array of p elements
var divTag = x.getElementsByTagName("div"); //creates an array of div elements
document.getElementById("demo").innerHTML = 'The first paragraph inside "main" is ' + pp[1].innerHTML;
function forLoopTest() {
var i;
for (i = 0; i < pp.length;i++) {
document.writeln("<br>" + pp[i].innerHTML;
}
}
var fragment = document.createDocumentFragment();
Array.prototype.forEach.call(document.getElementsByTagName('p'), function (element) {
Array.prototype.forEach.call(element.childNodes, function (childNode) {
fragment.appendChild(childNode.cloneNode(true));
});
});
document.body.appendChild(fragment);
</script>
</body>
</html>
if you read the error it tells you you have a syntax problem and are misisng a ).
You didn't close write()
document.writeln("<br>" + pp[i].innerHTML;
Should be
document.writeln("<br>" + pp[i].innerHTML);
DEMO
There are numerous way to do it, one solution might be.
HTML
<div id="main">
<p id="AA">A</p>
<p id="BB">B</p>
<p id="CC">C</p>
<p id="DD">D</p>
<p id="EE">E</p>
</div>
<p id="demo"></p>
Javascript
var fragment = document.createDocumentFragment();
Array.prototype.forEach.call(document.getElementsByTagName('p'), function (element) {
Array.prototype.forEach.call(element.childNodes, function (childNode) {
fragment.appendChild(childNode.cloneNode(true));
});
});
document.body.appendChild(fragment);
HTML after
<div id="main">
<p id="AA">A</p>
<p id="BB">B</p>
<p id="CC">C</p>
<p id="DD">D</p>
<p id="EE">E</p>
</div>
<p id="demo"></p>
ABCDE
On jsFiddle
Warning: cloneNode() may lead to duplicate element IDs in a
document.
This is also true if blindly copying the innerHTML of the elements.

Categories

Resources