Get content of all elements with the same class name using javascript.
How can I get all innerHTML-content from elements with the same class? I tried the code described below but it doesn't work I only get the first "Hello" from element but I don't get "World! from the second element" Of course there will be many more elements with the same class, not just two.
function myFunction() {
var child = document.querySelectorAll(".child");
var child, i;
for (i = 0; i < child.length; i++) {
var childall = child[i].innerHTML;
}
document.getElementById("demo").innerHTML = childall;
}
<div class="parent" id="parent">
<div class="child" id="child">Hello</div>
<div class="child" id="child">World!</div>
</div>
<button onclick="myFunction()">click</button>
<div class="demo" id="demo">
Move childall out of the loop, and assign an array to it. Now push all innerHTML values into it. After the loop ends join the array to a string, and assign to demo.
function myFunction() {
var child = document.querySelectorAll(".child");
var child, i;
var childall = [];
for (i = 0; i < child.length; i++) {
childall.push(child[i].innerHTML);
}
document.getElementById("demo").innerHTML = childall.join('<br>');
}
<div class="parent" id="parent">
<div class="child" id="child">Hello</div>
<div class="child" id="child">World!</div>
</div>
<button onclick="myFunction()">click</button>
<div class="demo" id="demo">
Instead of a for loop, you can use Array.from() to get an array of children's innerHTML.
function myFunction() {
const childall = Array.from(document.querySelectorAll(".child"), el => el.innerHTML);
document.getElementById("demo").innerHTML = childall.join('<br>');
}
<div class="parent" id="parent">
<div class="child" id="child">Hello</div>
<div class="child" id="child">World!</div>
</div>
<button onclick="myFunction()">click</button>
<div class="demo" id="demo">
Related
If the element has children insert a new div "i-new-element". parent2 and parent3 get a new div.
child3-parent3 has children but doesn't get a new giant. Why?
How can I make it possible for children who have children to get a new div?
it should look like:
<div id="child3-parent3">
<div id="i-new-element"></div>
<div id="child3"></div>
<div id="child4"></div>
</div>
var container = document.getElementById("container").querySelectorAll("#container > *");
container.forEach(function(div) {
{
if (div.hasChildNodes()) {
let parentElement = div;
let theFirstChild = parentElement.firstChild;
let newElement = document.createElement("div")
newElement.id = "i-new-eleemnt"
parentElement.insertBefore(newElement, theFirstChild)
}
}
});
<div id="container">
<div id="parent1"></div>
<div id="parent2">
<div id="child1"></div>
<div id="child2"></div>
<div id="child3-parent3">
<div id="child3"></div>
<div id="child4"></div>
</div>
</div>
<div id="parent3">
<div id="child5"></div>
<div id="child6"></div>
</div>
</div>
Using
var container = document.getElementById("container");
var elements = container.querySelectorAll(":scope *");
instead of
var container = document.getElementById("container").querySelectorAll("#container > *");
should fix your problem.
var container = document.getElementById("container");
var elements = container.querySelectorAll(":scope *");
elements.forEach(function(div){
{
if (div.hasChildNodes()) {
let parentElement = div;
let theFirstChild = parentElement.firstChild;
let newElement = document.createElement("div")
newElement.id = "i-new-eleemnt"
parentElement.insertBefore(newElement, theFirstChild)
}
}
});
<div id="container">
<div id="parent1"></div>
<div id="parent2">
<div id="child1"></div>
<div id="child2"></div>
<div id="child3-parent3">
<div id="child3"></div>
<div id="child4"></div>
</div>
</div>
<div id="parent3">
<div id="child5"></div>
<div id="child6"></div>
</div>
</div>
Edit: Further information about the :scope CSS pseudo-class can be found here and here.
I believe your problem is the following, even it is not described well in your sample HTML:
<div id="parent1"></div> per instance is actually not an empty node but contains some text i.e. <div id="parent1">some text here</div>.
You might believe or not, but node.hasChildNodes() will count any text as a child node (text node, nodeType = 3), so it will always return true is any text is present.
To avoid that, you can filter the text nodes first or just use this workaround:
Replace this line:
if (div.hasChildNodes()) {
with that line:
if (div.children.length) {
children property is not counting text nodes.
That's all you have to do, I believe.
var container = document.querySelectorAll("#container > *");
container.forEach(function(div) {
{
if (div.children.length) {
let parentElement = div;
let theFirstChild = parentElement.children[0];
let newElement = document.createElement("div")
newElement.id = "i-new-eleemnt";
newElement.innerHTML = 'i-new-eleemnt'
parentElement.insertBefore(newElement, theFirstChild);
}
}
});
<div id="container">
<div id="parent1">parent1</div>
<div id="parent2">parent2
<div id="child1">child1</div>
<div id="child2">child2</div>
<div id="child3-parent3">child3-parent3
<div id="child3">child3</div>
<div id="child4">child4</div>
</div>
</div>
<div id="parent3">parent3
<div id="child5">child5</div>
<div id="child6">child6</div>
</div>
</div>
I have the following html structure.
<div id="page1" class="page">
<div class="firstchild"></div>
<div class="secondchild"></div>
<div class="thirdchild"></div>
<div class="forthchild"></div>
</div>
<div id="page2" class="page">
<div class="firstchild"></div>
<div class="secondchild"></div>
<div class="thirdchild"></div>
<div class="forthchild"></div>
</div>
<div id="page3" class="page">
<div class="firstchild"></div>
<div class="secondchild"></div>
<div class="thirdchild"></div>
<div class="forthchild"></div>
</div>
And my javascript structure is.
var pageCLASS = frame.querySelectorAll(".page");
//var pageCLASS = frame.getElementsByClassName('page')[0];
var leng = pageCLASS.length;
for (var i = 0; i < leng; ++i) {
var pageID = frame.getElementById('page' + (i + 1));
var firstchild = frame.getElementsByClassName('firstchild')[0];
var secondchild = frame.getElementsByClassName('secondchild')[0];
var thirdchild = frame.getElementsByClassName('thirdchild')[0];
pageID.insertBefore(thirdchild, firstchild.nextSibling);
//pageCLASS.insertBefore(thirdchild, firstchild.nextSibling);
}
Now I have problems with the thirdchild being moved to below the firstchild and above the secondchild in all of page1, page2, and page3 together. The code above only moves it in page1, but for the other 2 which does nothing. The frame shown in the source is an iframe stored on the same domain with access to it's elements. Can I please get some advice on what I am doing wrong as I want to move all thirdchilds in each div to below the first child in each of their parent div?
The problem you are having is that you are constantly targeting the same elements with e.g.
var firstchild = frame.getElementsByClassName('firstchild')[0];
because this instruction always returns the first occurrence of such an element in the iframe and never the second or third.
In order to be sure that you are targeting the correct elements you can rewrite some of your code to only search for the elements that are contained within a certain parent and not inside the whole iframe.
You can then use something like this instead
var firstChild = pageID.querySelector('.firstchild');
which will only search for an element (the first occurrence) with class firstchild that is contained within some other element (in this case the element saved in pageID).
Check below (I exchanged the form for document so we can test here):
var pageCLASS = document.querySelectorAll(".page");
var leng = pageCLASS.length;
for (var i = 1; i <= leng; i++) {
var pageID = document.getElementById('page' + i);
var firstChild = pageID.querySelector('.firstchild');
var thirdChild = pageID.querySelector('.thirdchild');
firstChild.parentNode.insertBefore(thirdChild, firstChild.nextSibling);
}
.page {
border: 1px solid #09f;
}
<div id="page1" class="page">
<div class="firstchild">first child</div>
<div class="secondchild">second child</div>
<div class="thirdchild">third child</div>
<div class="forthchild">fourth child</div>
</div>
<div id="page2" class="page">
<div class="firstchild">first child</div>
<div class="secondchild">second child</div>
<div class="thirdchild">third child</div>
<div class="forthchild">fourth child</div>
</div>
<div id="page3" class="page">
<div class="firstchild">first child</div>
<div class="secondchild">second child</div>
<div class="thirdchild">third child</div>
<div class="forthchild">fourth child</div>
</div>
I have HTML elements iterated using a javascript loop
The html looks like this
<div class="description">Item 1</div>
<div class="description">Item 2</div>
<div class="description">Item 2</div>
The Javascript
let allItems = document.querySelectorAll(".description")
for (let i = 0; i <= allItems.length; i++) {
allItems[i].addEventListener("click", toggleSpinner.bind(this));
}
toggleSpinner = () => {
alert("I clicked") // here should be, for example, "I clicked Item 1,
// Or Item 2 or Item 3 depending on which was clicked
},
How do I call the function independently when each of the element is clicked
You could use something like this maybe?
toggleSpinner = (data) => {
console.log(`You clicked item ${data}`) // here should be, for example, "I clicked Item 1,
// Or Item 2 or Item 3 depending on which was clicked
}
let allItems = document.querySelectorAll(".description")
for (let i = 0; i < allItems.length; i++) {
allItems[i].addEventListener("click", toggleSpinner.bind(this, allItems[i].dataset.item));
}
<div class="description" data-item="1">Item 1</div>
<div class="description" data-item="2">Item 2</div>
<div class="description" data-item="3">Item 3</div>
let allItems = document.querySelectorAll(".description")
for (let i = 0; i <= allItems.length; i++) {
allItems[i].addEventListener("click", () => {toggleSpinner(allItems[i].innerHTML)});
}
toggleSpinner = content => {
alert(I clicked ${content})
},
Something like that. Add a parameter to the function and define what you want to add as this content in the loop
Are you looking something like this?
$(document).ready(function(){
$('div > *').click(function(){
alert('hi');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div>
<p> This is a paragraph </p>
<section> This is a section </section>
<span> This is a span </span>
<article> This is an article </article>
</div>
document.getElementById("getClickedElement").addEventListener("click", function(event) {
console.log("Clicked element is:- ", event.target.innerHTML);
});
<div id="getClickedElement">
<div class="description">Item 1</div>
<div class="description">Item 2</div>
<div class="description">Item 3</div>
</div>
Note:- Simply You have to wrap all the elements inside the parent div & bind addEventListener with that element. you will get targeted element data.
I am trying to loop over elements with a specific class and attach an ID to them.
var items = document.getElementsByClassName("item");
for(var i = 0; i < items.length; i++)
{
items[i].id = "item_" + i;
}
console.log(items);
If I run that I get the error Cannot set property 'id' of undefined
However the console.log(items) returns me the correct collection of items:
HTMLCollection []
0: div.item
1: div.item
length: 2
__proto__: HTMLCollection
But as soon as I try to get the index console.log(testimonials[0]) it is undefined.
HTML:
<div class="slider">
<div class="item">
Item 1
</div>
</div>
<div class="slider">
<div class="item">
Item 2
</div>
</div>
The issue could be your script is running before the DOM is fully ready.
To solve the issue, you can place your code at the bottom of the body.
OR:
Try wrapping your code with DOMContentLoaded, this will ensure that your code will be executed once the DOM is fully ready.
<script>
document.addEventListener("DOMContentLoaded", function(event) {
var items = document.getElementsByClassName("item");
for(var i = 0; i < items.length; i++)
{
items[i].id = "item_" + i;
}
console.log(items);
});
</script>
<div class="slider">
<div class="item">
Item 1
</div>
</div>
<div class="slider">
<div class="item">
Item 2
</div>
</div>
With vanilla js always do DOM related operations after DOM is ready to use. And also before accessing/working with any DOM element check that it isn't nullable (not equal to null). With these practices you won't see any error with DOM elements because it is the safe way with manipulating with DOM elements. In regular loop always cache array.length. Avoid using anonymous function it is non-future proof and not debug-friendly way. Also write all js in separate js file.
HTML
<div class="slider">
<div class="item">
Item 1
</div>
</div>
<div class="slider">
<div class="item">
Item 2
</div>
</div>
JS
document.addEventListener("DOMContentLoaded", onDomReadyHandler);
function onDomReadyHandler(event) {
var items = document.getElementsByClassName('item');
var itemsLen = items.length;
for(var i = 0; i < itemsLen; i++) {
items[i].id = "item_" + i;
}
console.log(items);
}
Check this code:
<html>
<head>
<script>
window.onload = function(e){
var allItem = document.getElementsByClassName("item");
for(var i = 0; i < allItem.length; i++)
{
document.getElementsByClassName("item")[i].setAttribute("id", "item_" + i);
}
};
</script>
</head>
<body>
<div class="slider">
<div class="item" id="">
Item 1
</div>
</div>
<div class="slider">
<div class="item" id="">
Item 2
</div>
</div>
</body>
</html>
Hope it helps you.
Try using
items[i].setAttribute("id", "item_" + i);
Fore more details you can visit documentation of
https://www.w3schools.com/jsref/met_element_setattribute.asp
https://www.w3schools.com/jsref/met_element_getattribute.asp
Fiddle for it:
https://jsfiddle.net/abdulrauf618/n14v58zs
I have HTML File:
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="Function()">Whatever</button>
<div id="result"></div>
I'd like my function to take values from all four divs with class "um-field-value"
<div class="um-field-value">Value1</div>
And past them in Div "result"
Essentially, I want a script to simply copy values given in class um-field-value and paste it in a "result" div. I tried following:
function Function() {
var x = document.getElementsByClassName("um-field-value");
document.getElementsById('result').innerHTML = x;
}
But that doesn't work at all.
I am somewhat new to coding so I am not entirely sure if it is even possible. Googled for over an hour but couldn't find any solutions.
document.getElementsByClassName gets the HTML nodes themselves but then you have to extract the values from within the HTML nodes, combine them, and set that to your result div. Example snippet below:
function myFunction() {
var valueNodes = Array.prototype.slice.call(document.getElementsByClassName("um-field-value"));
var values = valueNodes.map(valueNode => valueNode.innerHTML);
var result = values.join(' ');
document.getElementById('result').innerHTML = result;
}
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="myFunction()">Whatever</button>
<div id="result"></div>
Use querySelectorAll to get all the dom with this class um-field-value and iterate over that to get the innerHTML
There is a typo in your code.It is getElementById instead of getElementsById. There is an extra s
function Function() {
var x = document.querySelectorAll(".um-field-value");
let result = '';
for (var y = 0; y < x.length; y++) {
result += x[y].innerHTML;
}
document.getElementById('result').innerHTML = result;
}
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="Function()">Whatever</button>
<div id="result"></div>
You are on the right track. document.getElementsByClassName will return a NodeList. You need to get the innerText for each of the elements in that list. Depending on the browser you can either use forEach or a regular for loop to iterate over the list.
function Function() {
var fieldsList = document.getElementsByClassName("um-field-value");
var fieldValues = [];
fieldsList.forEach(function(field) { fieldValues.push(field.innerText) });
document.getElementsById('result').innerHTML = fieldValues.join(", ");
}
This is a simple and readable solution that uses a loop to get the text inside each element and add it to a string. getElementsByClassName returns an array of all elements found, so a loop is needed to get the text inside each with textContent.
function Function() {
var result = '';
var fields = document.getElementsByClassName("um-field-value");
for (var i=0; i<fields.length; i++) {
result += fields[i].textContent + '\n';
}
document.getElementById('result').innerHTML = result;
}
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="Function()">Whatever</button>
<div id="result"></div>