I'm trying to make a chrome extension. A part of the code (early on in the making of this extension) involves fetching several elements by their class name. There are several elements whos class name all look like this: "scollerItem [AlotOfRandomCharacters]".
So I'm trying to list all classNames that start with "scrollerItem", but i'm not quite sure how to go about it.
So here's my code so far:
function initRE(){
var matchingItems = [];
var allElements = document.getElementsByTagName("div");
for(i=0; i < allElements.length; i++)
{
if ( allElements [i].className == "scrollerItem" && "*" )
{
matchingItems.push(allElements[i]);
}
}
alert(matchingItems[0]);
}
allElements is listed in the breakpoint watchlist as "HTMLCollection(623)" (roughly), but nothing is forwarded to the "matchingItems" array.
I've tried [i].className.contains and .includes
Direct copy of one of the HTML Elements in question:
<div class="scrollerItem s1d8yj03-2 ebdCEL Post t3_agnhuk s1ukwo15-0 RqhAo" id="t3_agnhuk" tabindex="-1">
You can try to use Document.querySelectorAll() with a CSS selector matching all classes starting with your target string.
let elems = document.querySelectorAll("div[class^='scrollerItem'], div[class*=' scrollerItem]");
let classes = Array.from(elems).map(e => Array.from(e.classList)).reduce((arr, res) => {
res = res.concat(arr);
return res;
}, []).filter(cls => cls.startsWith('scrollerItem'))
Additional explanation of CSS selector syntax: Is there a CSS selector by class prefix?
Since the class scrollerItem exists on the element, you can use document.querySelectorAll() with the .scrollerItem as the query:
const result = document.querySelectorAll('.scrollerItem');
console.log(Array.from(result));
<div class="scrollerItem s1d8yj03-2 ebdCEL Post t3_agnhuk s1ukwo15-0 RqhAo" id="t3_agnhuk" tabindex="-1">
Use classList not className:
if (allElements[i].classList.contains("scrollerItem") {...}
Related
I have a nodelist of elements in js that were collected by querying many classes and then a "for" statement that loops through the list. What I need is a quicky one-line way to return what class each element was selected by within the loop so I can perform an action based on that. Here is my code blip:
var nodeList = document.querySelectorAll(".class1, .class2, .etc...");
for (var i = 0; i < nodeList.length; i++) {
var classOfCurrentDiv = [...]
//perform action using classOfCurrentDiv
}
I know I can do something like
if (nodeList[i].classList.contains(class1)) {
//perform code
}
and repeat that for each class, or do a comparison of the element's classlist and the list of classes I'm searching for, but all I need to do is insert the name of the class into a string, so I'd prefer a single line solution to obtain the class that returned the element in the query. The class that returned the element may not be that element's only class which is why I can't just pull the element's classlist.
This is probably very simple and I'm just blanking on how to do it, but let me know. The list of queried classes will be hardcoded and each element's classlist will only contain one of the queried classes if that helps.
Thanks!
You can use Element.matches to do this with a 1 liner.
Element.matches(selector) lets you specify a css selector to an element and it will return if the element is matched by the selector. Since your selector works out to be a comma separated list of classes, you can find which class matched the particular element by splitting the selector on commas to an array, loop thru that array as each class via filter and filter out elements that don't match. Full example below:
function classOfCurrentDiv(div, selector) {
return selector.split(", ").filter(_class => div.matches(_class))[0];
}
const selector = ".class1, .class2, .class3";
const nodeList = document.querySelectorAll(selector);
for (let i = 0; i < nodeList.length; i++) {
console.log("selector of element " + i + ":", classOfCurrentDiv(nodeList[i], selector));
}
<div class="class1 foo"></div>
<div class="class3 bar"></div>
<div class="class2 baz"></div>
Something like that ?
const classList = [".ps-fixed", ".class1", ".class2"]
const nodeList = document.querySelectorAll(classList)
nodeList.forEach((node) => {
classList.forEach((ClassMatch) => {
if (node.classList.contains(ClassMatch.slice(1))) { //slice 1 to remove the "." before the class names in the array
console.log(node)
}
})
});
I want to use lazy loading effect and in my code everything is going ok, but querySelector section.
I've stored some elements in a variable and I wanna apply observer function on theme.
And I also print every output in console.log to see the things.
But this error happens:
Uncaught TypeError: imgs.forEach is not a function
This is my code:
const imgs = document.querySelector("[data-src]");
const options = {
threshold:1,
};
const observer = new IntersectionObserver((entries,observer) => {
entries.forEach(entry => {
let src = entry.target.getAttribute('data-src');
if(!entry.isIntersecting){
return;
}
entry.target.src=src;
console.log(entry)
observer.unobserve(entry.target);
})
},options)
// Probleme is here
imgs.forEach(img => {
observer.observe(img);
})
Try with querySelectorAll like below code,
const imgs = document.querySelectorAll("[data-src]");
as querySelector will return single matched element, but querySelectorAll will return an NodeList of all matched elements.
Use querySelectorAll instead that should fix it
Reference the mdn documentation
The Document method querySelectorAll() returns a static (not live)
NodeList representing a list of the document's elements that match the
specified group of selectors.
instead of
const imgs = document.querySelector("[data-src]");
try this
const imgs = document.querySelectorAll("[data-src]");
Although for some browser using querySelectorAll(selector).forEach() will work. But it is not supported by all browsers. So the safe way to do this is using a for loop for looping over the NodeList. So you should do something like this,
const imgs = document.querySelector("[data-src]");
// other coddes...
for(let i = 0; i<imgs.length; i++) {
// your code.
}
I think this will be the safest way.
Document.querySelector()
returns a single element and you cannot loop over a single element.
document.querySelectorAll()
returns all the elements with the class, id, tagname etc provided in the parenthesis.
I want to use lazy loading effect and in my code everything is going ok, but querySelector section.
I've stored some elements in a variable and I wanna apply observer function on theme.
And I also print every output in console.log to see the things.
But this error happens:
Uncaught TypeError: imgs.forEach is not a function
This is my code:
const imgs = document.querySelector("[data-src]");
const options = {
threshold:1,
};
const observer = new IntersectionObserver((entries,observer) => {
entries.forEach(entry => {
let src = entry.target.getAttribute('data-src');
if(!entry.isIntersecting){
return;
}
entry.target.src=src;
console.log(entry)
observer.unobserve(entry.target);
})
},options)
// Probleme is here
imgs.forEach(img => {
observer.observe(img);
})
Try with querySelectorAll like below code,
const imgs = document.querySelectorAll("[data-src]");
as querySelector will return single matched element, but querySelectorAll will return an NodeList of all matched elements.
Use querySelectorAll instead that should fix it
Reference the mdn documentation
The Document method querySelectorAll() returns a static (not live)
NodeList representing a list of the document's elements that match the
specified group of selectors.
instead of
const imgs = document.querySelector("[data-src]");
try this
const imgs = document.querySelectorAll("[data-src]");
Although for some browser using querySelectorAll(selector).forEach() will work. But it is not supported by all browsers. So the safe way to do this is using a for loop for looping over the NodeList. So you should do something like this,
const imgs = document.querySelector("[data-src]");
// other coddes...
for(let i = 0; i<imgs.length; i++) {
// your code.
}
I think this will be the safest way.
Document.querySelector()
returns a single element and you cannot loop over a single element.
document.querySelectorAll()
returns all the elements with the class, id, tagname etc provided in the parenthesis.
I have two the same forms on the same page and script that works only for the first form.
I'm a beginner and this is a challenge for me; I tried add the `for (var i = 0; i < input.length; i++) but it doesn't work out. I will be grateful for any help.
var el = document.querySelector(".js-tac");
input = document.querySelector('.js-tel')
input.addEventListener('input', evt => {
const value = input.value
if (!value) {
el.classList.remove("is-visible");
return
}
const trimmed = value.trim()
if (trimmed) {
el.classList.add("is-visible");
} else {
el.classList.remove("is-visible");
}
})
document.querySelector return the first matched element. So you need document.querySelectorAll which will give a collection. Then iterate that collection like this
document.querySelectorAll('.js-tel').forEach((input)=>{
// not using arrow function since using this to target the element
input.addEventListener('input', function(evt){
const value = this.value
// rest of the code
})
})
The problem is that you are only getting one input element. (querySelector returns the first matching element, not all matching elements). You likely want to use querySelectorAll to get a NodeList (which will contain all matching nodes). You can iterate over those.
Based on how you seem to be using it, I'd recommend making sure your js-tac and js-tel are wrapped in some common parent, and use querySelectorAll to find those. Then, you can use querySelector to find the js-tel and js-tac.
var nodes = document.querySelectorAll('.js-parent')
//If you don't export forEach to be available, you can also just do a standard
//for loop here instead.
nodes.forEach((parent) => {
var el = parent.querySelector(".js-tac");
input = parent.querySelector('.js-tel')
...
})
I am using querySelectorAll property initially to obtain nodelists of certain tags,and then from this nodelist i am iterating through each node looking for a certain match to an id property using querySelector,however the result always is null.
var x=document.body.querySelectorAll("script");
for(var i=0;i<x.length;++i)
{
var y=x[i].querySelector("#myid");
console.log(y);
if(y!== null)
{
console.log(i+1);
}
}
i always get an output of null,please help.
If you want to select for example script tags that have the name attribute equal to myName use this:
var elems = document.querySelectorAll('script[name = "myName"]');
You can put as many CSS selectors as ou want to narrow the search.
If you want for example to select div elements that are direct children of li element, and that have the attribute name begin with "abc" and that have an id and a class someClass then use this:
var elems = document.querySelectorAll('li > div[name ^= "abc"][id].someClass');
Here is link to all CSS Selectors!
Krishna your querySelectorAll will grab a nodelist for you. There is no reason for you to add an additional query selector within your loop.
var myId = document.querySelector('#myid');
var collection = document.body.querySelectorAll("script");
for (var i = 0; i < collection.length; i++) {
if (collection[i].includes(myId)) {
console.log(i+1);
}
}