Select nested elements by name attribute javascript(no jquery) - javascript

So I have this HTML code and I need to select the elements by their name attribute. The problem is I have multiple elements with the same structure and I need to go throw them with a loop.
<div class="res">
<h4 name="title">title</h4>
<span name="span1"></span>
<span name="span2"></span>
<p name="p1"></p>
<p name="p2"></p>
</div>
I need to select each one of the elements inside the .res div element by their name(or if there's a better solution I'd like to you).

document.getElementsByName("res");
document.getElementsByName("title");
document.getElementsByName("span");
or you can loop through the elements if you don't want to hard-code the name.

You could use .querySelector() like :
document.querySelector('[name="xxxxxx"]');
If you want to loop through all the res containers you could use .querySelctorAll() like :
var containers = document.querySelectorAll('.res');
for( var i = 0; i < containers.length; i++) {
console.log( containers[i].querySelector('[name="title"]').textContent );
}

You can use the DOM Element.children attribute in pure javascript
var children = res.children;
for (var i = 0; i < children.length; i++) {
var child = children[i];
// Do stuff
}

You can use querySelectorAll and inside loop handle every element.
const elements = document.querySelectorAll(".res > *");
elements.forEach(element => {
console.log(element);
});
<div class="res">
<h4 name="title">title</h4>
<span name="span1"></span>
<span name="span2"></span>
<p name="p1"></p>
<p name="p2"></p>
</div>

Related

Selecting multiple second instances of a queryselectorAll element?

I am using Chartist and I need to send some data to the repeated second occurrence of an element. For example, there are two "ct-bar" elements inside every "ct-series" element. I need to select the second "ct-bar" element that is contained in each of the "ct-series" elements. I have tried doing this with a for loop and some other ways to no avail. How can I achieve this?
JS
const series = xChart.querySelectorAll('.ct-series .ct-bar')
for (var i = 0; i < series.length; i++) {
this.element = series[i];
var seriesNext = series[1]
}
Use the :nth-child() selector to get the 2nd child of each series.
const bars = xChart.querySelectorAll('.ct-series > .ct-bar:nth-child(2)');
You can use the :nth-child(2) css selector to just grab the 2nd ct-bar child under each ct-series. See below for how this would work.
const series = document.querySelectorAll('.ct-series > .ct-bar:nth-child(2)')
for (var i = 0; i < series.length; i++) {
console.log(series[i].textContent);
}
<div class="ct-series">
<span class="ct-bar">foo 1</span>
<span class="ct-bar">bar 1</span>
</div>
<div class="ct-series">
<span class="ct-bar">foo 2</span>
<span class="ct-bar">bar 2</span>
</div>

CSS selector to match elements by attribute's name start

Is there any CSS selector to match these elements? (I need it for adblocker config, looked at W3C selectors document - no hints found there. Generic solution needed because part after data-d- gets randomized by the site).
<div data-d-9y3x>
<div data-d-m01>
<div data-d-whatever>
No, there is currently no way to select elements based on the presence of an attribute whose name is starting with a certain value. The starts with selection is only possible for attribute values.
Such a selector is not mentioned in the CSS Selectors Level 4 spec also and so it doesn't look like it would be available anytime soon.
You have the following choices:
Use group of selectors with all possible attribute name values in the format element[attribute-name]. But this option is not viable when the exact attribute names are not fixed/unknown.
Use JavaScript (or some other scripting library of your preference). Below is a very quick rough sample for the benefit of future visitors.
var el = document.getElementsByTagName('div');
for (var i = 0; i < el.length; i++) {
var attr = el[i].attributes; /* get all attributes on the element */
for (var j = 0; j < attr.length; j++) {
if (attr[j].name.indexOf('data-') == 0) { /* if element has an attribute whose name has data- */
el[i].style.color = 'red';
break;
}
}
}
<div data-d-9y3x>Some</div>
<div data-d-m01>text</div>
<div data-d-whatever>content</div>
<div test-data-d-whatever>and</div>
<div d-whatever>more</div>
<div testdata-d-whatever>...</div>
With ES6+ you can use spread operator (...) and then filter those element that their attribute names' start with data-d-:
var res = [...document.querySelectorAll("*")]
.filter(t => [...t.attributes]
.filter(({ name }) => name.startsWith("data-d-")).length > 0)
console.log(res);
<div data-d-9y3x>Some</div>
<div data-d-m01>text</div>
<div data-d-whatever>content</div>
<div test-data-d-whatever>and</div>
<div d-whatever>more</div>
<div testdata-d-whatever>...</div>

Get all tag nodes inside another tag recursively

I have an html document consists of a <div id = "main">. Inside this div may be several levels of nodes, without a precise structure because is the user who creates the document content.
I wanto use a JavaScript function that returns all nodes within div id = "main". Any tag is, taking into account that there may be different levels of children.
For now I have this function that returns all tags, even those outside to div id = "main":
function getNodes() {
var all = document.getElementsByTagName("*");
for (var elem = 0; elem < all.length; elem++) {
//do something..
}
}
As such this document:
<div id="main">
<h1>bla bla</h1>
<p>
<b>text text text </b> text text <i>text</i>.
<img src=".."></img>
</p>
<div>
<p></p>
<p></p>
</div>
<p>..</p>
</div>
The function getNodes would return an array of object nodes (I don't know how to represent it, so I list them):
[h1, p, b, i, img, div, p, p, p]
Thank you
Use document.querySelectorAll. It returns a NodeList, not an array, but you can loop over it in the same way:
function getNodes() {
var all = document.querySelectorAll("#main *");
for (var elem = 0; elem < all.length; elem++) {
//do something..
}
}
http://jsfiddle.net/suuja4L5/
Just get the parent element and then get the descendents just as you did:
var mainDiv = document.getElementById("main");
mainDiv.getElementsByTagName("*")
if you want all child of <div id="main">,then use the following :
var children = document.querySelector("#main").children;

Why wont my onclick not remove any of my classes?

I have a huge problem here.
I can't get my onclick to work as I want .. So I hope someone here can help me.
#NiceToKnow
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="video"></div>
I want it to display: none; every of my class="nice", so you only can see class="video", but nothing happens at all.
You are selecting the elements of the class not the class itself. So you will have to loop through the elements as javascript can only edit what is in the DOM not the CSS classes that effect your elements. So getElementsByClassName returns an array of nodes in which we must loop through and hide each one. Click runsnippet below to see this work
function changeNice(){
//ASSIGN ELEMENTS TO ARRAY
elementsofClass=document.getElementsByClassName('nice');
for(i=0; i<elementsofClass.length; i++){
//HIDE SELECTED ELEMENT
elementsofClass[i].style.display='none';
}}
#NiceToKnow
<div id="cards1" class="nice">TEST 1</div>
<div id="cards2" class="nice">TEST 2</div>
<div id="cards3" class="nice">TEST 3</div>
<div id="cards4" class="video">I don't HIDE</div>
Also don't use duplicate ID. This will cause errors later when trying to select your elements.
The getElementsByClassName will return an array, so we need to iterate through the array and hide one by one.
So it is better to declare a function and define the logic inside that. Please see the example below.
window.hideAllniceClass = function () {
var elems = document.getElementsByClassName('nice');
for (var i = 0; i != elems.length; ++i) {
elems[i].style.display = "none"; // hidden has to be a string
}
}
#NiceToKnow
<div id="cards1" class="nice">Test Content</div>
<div id="cards2" class="nice">Test Content</div>
<div id="cards3" class="nice">Test Content</div>
<div id="cards4" class="video">Test Video Content</div>
DEMO
Change your code to something like that:
var elems = document.getElementsByClassName('nice');
for(var i = 0; i < elems.length; i++) {
elems[i].style.display = 'none'
}
You have to iterate on the results returned by getElementsByClassName.
jsfiddle
You can create a loop that will loop through all the nice elements and then display none like this: https://jsfiddle.net/7vf9pz8u/
<script>
function hide(){
for(ct=0; ct < 3; ct++){
document.getElementsByClassName('nice')[ct].style.display='none'
}
}
</script>
getElementsByClassName returns array of all the match elements so you will have to provide index or loop through all of them to change their property.
Change your code to this
document.getElementsByClassName('nice')[0].style.display='none'
//For every element
var e = document.getElementsByClassName('nice');
for (i = 0; i < e.length; i++) {
e[i].style.display = "none";
}
As your divs do not have unique names they are in an array cards[].
So to access a particular div you need to reference the the array to that particular div. The quoted solution should work.

JavaScript - how to delete elements that do not have a specific class?

I want to delete all elements that do not have the class 'stay'
For example:
<div class="stay">Stay</div>
<div class="stay">Stay</div>
<div class="go">Go</div>
<div class="element">Stay</div>
<div class="Sel">classy</div>
I would like some javascript that would delete the elements that do not have the class stay and Sel, without having to list the classes go and element
I have used:
var els = document.querySelectorAll('#parent :not(.stay)');
for (var i = 0; i < els.length; i++) {
els[i].parentNode.removeChild(els[i])
}
from the first answer, but am unsure of how to keep the class 'Sel'.
Also, I DO NOT want any Jquery.
When you are doing such an operation should need to target a particular parent element, else it could also remove elements like html/body etc.
So assuming you have a parent node, you can use querySelectorAll in conjunction with :not() selector
<div id="parent">
<div class="stay">Stay</div>
<div class="stay">Stay</div>
<div class="go">Go</div>
<div class="element">element</div>
</div>
then
var els = document.querySelectorAll('#parent :not(.stay)');
for (var i = 0; i < els.length; i++) {
els[i].parentNode.removeChild(els[i])
}
Demo: Fiddle

Categories

Resources