VanillaJS: grab the text from multiple elements (same class) and list in separate div - javascript

I'm trying to get the text content of a specific class across the page, then print them out in a different div, separated by a comma.
Example:
<!-- Within the HTML Page -->
<div class="copyright">Image one</div>
<div class="copyright">Image two</div>
<div class="copyright">Image three</div>
<!-- Should output: "Image one, Image two, Image three" -->
<div class="showCopyright"></div>
How would I achieve this using only pure VanillaJS, not jQuery?
Would I use the innerHTML? or innerText?
I really appreciate any help you can provide.

I would use textContent unless there is or you want markup in the result
window.addEventListener("DOMContentLoaded", () => {
document.querySelector(".showCopyright")
.textContent = [...document.querySelectorAll(".copyright")]
.map(({ textContent }) => textContent.trim()).join(", ");
});
<!-- Within the HTML Page -->
<div class="copyright">Image one</div>
<div class="copyright">Image two</div>
<div class="copyright">Image three</div>
<!-- Should output: "Image one, Image two, Image three" -->
<div class="showCopyright"></div>

Here is a pure javascript method to do that:
var textArray = [];
var elements = document.getElementsByClassName("copyright");
for (var i = 0; i < elements.length; i++) {
textArray.push(elements[i].innerText);
}
document.getElementsByClassName("showCopyright")[0].innerText = textArray.join(', ');
<div class="copyright">Image one</div>
<div class="copyright">Image two</div>
<div class="copyright">Image three</div>
<div class="showCopyright"></div>

Related

How to retrieve the div first child element sibling node using querySelector?

I have the DOM structure like below
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div><!-- want to access this div content -->
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
From the above HTML I want to access the div content of second div with classname table_cell inside first table_row div.
So basically I want to retrieve the content of div with classname table_cell with content chocolate products.
I have tried to do it like below
const element = document.querySelector('.rdt_TableBody');
const element1 = element.querySelectorAll('.rdt_TableRow')[0]
const element2 = element1.querySelectorAll('.rdt_TableCell')[0].innerHTML;
When I log element2 value it gives some strange output and not the text "chocolate products"
Could someone help me how to fix this. Thanks.
You can use:
the :nth-of-type pseudo-selector
combined with the immediate-child selector (>)
Example:
const selectedDiv = document.querySelector('.table_body > div:nth-of-type(1) > div:nth-of-type(2)');
Working Example:
const selectedDiv = document.querySelector('.table_body > div:nth-of-type(1) > div:nth-of-type(2)');
selectedDiv.style.color = 'white';
selectedDiv.style.backgroundColor = 'red';
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div> //want to access this div content
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
In your code
element1.querySelectorAll('.table_cell')[0], this is targeting the first element i.e., <div class="table_cell">first</div>. That's the reason why you are not getting the expected output.
I have made it to element1.querySelectorAll('.table_cell')[1], so that it'll target <div class="table_cell">chocolate products</div>.
const element = document.querySelector('.table_body');
const element1 = element.querySelectorAll('.table_row')[0]
const element2 = element1.querySelectorAll('.table_cell')[1].innerHTML;
console.log(element2);
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div>
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
Since the element that you want to target is the last div with having class table_cell, you can use :last-of-type on table_cell class using document.querySelector. But otherwise you can also use :nth-of-type if there are more than 2 elements and you want to target any element in between first and last.
Below is the example using :last-of-type.
const elem = document.querySelector(".table_row > .table_cell:last-of-type");
console.log(elem?.innerHTML);
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div> //want to access this div content
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
For more info you can refer :nth-of-type, :last-of-type and child combinator(>).

Vanilla Javascript insertBefore() in for loop

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>

Get all element of same class and detect first element from that via jquery

I've dynamic structure where data is coming in below way. I want to filter all element with class name "My_data" and take first of it. in below code structure i want to get first "My_data" class element.
<div class="all_data">
<div class="listing">
<div class="other_1">Block One</div>
<div class="mbox">Block Two</div>
<div class="other_2">Block Three</div>
<div class="mbox">Block Four</div>
</div>
<div class="listing">
<div class="other_1">Block One</div>
<div class="mbox">Block Two</div>
<div class="other_2">Block Three</div>
<div class="mbox">Block Four</div>
</div>
<div class="listing">
<div class="other_2">Block One</div>
<div class="My_data">My data 1</div>
<div class="other_2">Block Three</div>
<div class="My_data">My data 2</div>
</div>
<div class="listing">
<div class="other_5">Block One</div>
<div class="My_data">My data 3</div>
<div class="other_2">Block Three</div>
<div class="My_data">My data 4</div>
</div>
</div>
so from above code structure I want to select My data 1
Please note: this data structure is dynamic so it might be change every time. sometimes first listing div get "My_data" class and some time no listing div has it.
Try this:
var myDataDiv = document.querySelector('.My_data')
var myData = myDataDiff && myDataDiff.innerText; // > string | null
document.querySelector('.My_data') will either return the first element with class My_data - if it exists - or null otherwise. Therefore myData will either be null or the result of myDataDiff.innerText.
Just make one empty div and append all child divs of listing class in it. After that take the first from that new list.

Reorder divs in javascript without jquery

lets say I have html:
<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div>
how would I in javascript and not jquery reorder these divs to:
<div id="1">1</div>
<div id="3">3</div>
<div id="2">2</div>
You can use display:flex and the order css (I had to add a letter before the number for your id as SO didn't seem to like it for the css)
.container {display:flex; flex-direction:column}
#s1 {order:1;}
#s2 {order:3;}
#s3 {order:2;}
<div class="container">
<div id="s1">1</div>
<div id="s2">2</div>
<div id="s3">3</div>
</div>
More information about order
More information about flex
Update
Sorry read the question wrong - thought you wanted to do it without js
var div = document.getElementById('3')
div.parentNode.insertBefore(div, document.getElementById('2'))
<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div>
The solution given by the duplicate questions are incorrect because they make the assumption that the elements are next to each other. But even in this simple example, there is a text node containing white-space between the elements.
Given that the two elements are not nested, you can use this to swap two elements:
function swapElements (first, second) {
var tmpNode = document.createElement('div');
tmpNode.setAttribute('id', '_tmp');
var firstParent = first.parentNode;
firstParent.insertBefore(tmpNode, first);
second.parentNode.insertBefore(second, first);
firstParent.insertBefore(second, tmpNode);
firstParent.removeChild(tmpNode);
}
Use it like:
var first = document.querySelector('#1');
var second = document.querySelector('#2');
swapElements(first, second);

How to Wrap all DIVs after or before specific DIVs using javascript or MooTools?

What I am trying to do is trying to wrap all DIVs after or before some specific DIVs.
here is the code:
<div class="heading">Heading one</div>
<div>question one</div>
<div>question two</div>
<div>question three</div>
<div class="heading">Heading two</div>
<div>question one</div>
<div>question two</div>
<div>question three</div>
<div>question four</div>
<div>question five</div>
<div>question six</div>
<div class="heading">Heading three</div>
<div>question one</div>
<div>question two</div>
so the questions within these heading DIVs I want to wrap them dynamically so if questions may be more or less for any heading will automatically wrap inside another div and will assign the ids or classes to them to show and hide.
Want to do it dynamically using JavaScript or mootools:
Remember that questions may vary as user adds from the Admin Panel against every heading.
Edit: Please also remember that Headings may also be vary may be more headings can be added by user and every heading can contain questions.
<div class="heading">Heading one</div>
<div id='one'>
<div>question one</div>
<div>question two</div>
<div>question three</div>
</div>
<div class="heading">Heading two</div>
<div id='two'>
<div>question one</div>
<div>question two</div>
<div>question three</div>
<div>question four</div>
<div>question five</div>
<div>question six</div>
</div>
<div class="heading">Heading three</div>
<div id='three'>
<div>question one</div>
<div>question two</div>
</div>
Please let me if you think the question is not good in comments so that if you rate down as bad I will not be able to ask more questions.
Thanks.
This should do it:
var newParent, id = 1;
$$('div').each(function (element) {
if (element.hasClass('heading')) {
newParent = new Element('div[id=heading_' + id + ']').inject(element, 'after');
id++;
} else {
newParent.wraps(element);
}
});
Example: jsFiddle
Or to make it without globals:
$$('div').each(function (element) {
if (element.hasClass('heading')) {
var id = $$('div[id^=heading_').length + 1;
var newParent = new Element('div[id=heading_' + id + ']').inject(element, 'after');
} else {
element.getPrevious().wraps(element);
}
});
Example: jsFiddle
The .wraps() method is the key here.
Applying the jquery solution already mentioned to mootools, you'd use the "GetUntil" method: http://mootools.net/forge/p/element_getuntil. And then wrap using wraps: http://mootools.net/docs/core/Element/Element#Element:wraps.
Demo
js
$('.heading + div').each(function () {
$(this).nextUntil(".heading").andSelf().wrapAll('<div class="content" />');
});
here it is with different IDs
Demo
js
var ID = 0;
$('.heading + div').each(function () {
ID++;
$(this).nextUntil(".heading").andSelf().wrapAll('<div class="content" />').attr('id', 'id' + ID);
});
Final Demo
js
$('.heading + div').each(function (index, element) {
$(this).nextUntil(".heading").andSelf().wrapAll('<div class="content" />');
$(element).parent().attr('id', 'id' + index);
});
I am using the index and element so the id count starts from 0
Not to effect the last one
Demo not to effect last
js
$('.heading:not(:last) + div').each(function (index, element) {
$(this).nextUntil(".heading").andSelf().wrapAll('<div class="content" />');
$(element).parent().attr('id', 'id' + index);
});

Categories

Resources