How get an array of the values of elements which have same class?
When I do this I get only the first element, but I want a whole array:
var classes = document.querySelector(".klass").value;
alert(classes); //Outputs only the first element
And I want to get a full array of the values of the inputs:
<input type="text" class="klass" />
<input type="text" class="klass" />
<input type="text" class="klass" />
Is that possible?
Use document.querySelectorAll to retrieve a NodeList (see also the section "How can I convert NodeList to Array?") then cast it to an array and map a function that returns each element's value.
var classesNodeList = document.querySelectorAll(".klass");
var classes = Array.prototype.slice.call(classesNodeList).map(function(element) {
return element.value;
});
Update
As stated in the comment by Ginden, a shorter way to do this is to pass the NodeList to Array.prototype.map using Function.prototype.call
var classesNodeList = document.querySelectorAll(".klass");
var classes = Array.prototype.map.call(classesNodeList, function(element) {
return element.value;
});
For such a simple CSS selector expression, I would use getElementsByClassName and give it the class name, rather than querySelectorAll. getElementsByClassName is generally faster than using querySelectorAll by several orders of magnitude. See this jsperf.
var classes = document.getElementsByClassName("klass"); // Do not use a period here!
var values = Array.prototype.map.call(classes, function(el) {
return el.value;
});
getElementsByClassName is usually faster than querySelectorAll. Browsers index elements by class name already to optimize the speed of CSS transformations. getElementsByClassName returns an HTMLCollection element, so it does not have the Array methods and you need to use Array.prototype... on this too.
You need to loop through your array of elements and get the value of each one.
var classes = document.querySelectorAll(".klass").value,
values = [];
for(var i = 0; i < classes.length; i++) {
values.push(classes[i].value);
}
Note that this may not be as clean as using [].map, but is a good deal faster.
You can use querySelectorAll method first and then use array's map function to retrieve the result:
var elements = document.querySelectorAll('.klass');
var values = [].map.call(elements, function(e) {
return e.value;
});
Related
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')
...
})
What I'm trying to do is something like this:
var textareas = document.getElementsByTagName("textarea");
var inputs = document.getElementsByTagName("input");
var selects = document.getElementsByTagName("select");
var concatenated = textareas.concat(inputs).concat(selects);
for(var i = 0; i < concatenated.length; i++) {
//Do something on each concatenated[i] item
}
You can use ES6:
const concatenated = [...textareas, ...inputs, ...selects];
From ES6 onwards, you can simply spread them into another array:
var concatenated = [...textareas, ...inputs, ...selects];
How about using 1 queryselector
<textarea value= "The DOM is very useful." />
<input class="intro" value='This example demonstrates the method' />
<script>
var z = document.querySelectorAll("input, textarea");
//now z has input and textarea
for(i=0;i<z.length;i++)
{
alert( z[i]);
}
</script>
You can use Array.prototype to make use of Array methods on array-like objects. In this case, you can create a small helper function to call slice on your collections, turning them into arrays:
function toArray(collection){ return Array.prototype.slice.call(collection, 0) }
So your queries get structured like this instead:
var textareas = toArray(document.getElementsByTagName("textarea"));
Then, you're free to use concat to join them.
Even better, you can use document.querySelectorAll to just get them all in the first place, then loop over them:
var concatenated = document.querySelectorAll('textarea, input, select')
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);
}
}
I am currently having problem with selecting and matching the innerHTML using querySelectorAll.
Here is what i did:
document.querySelectorAll('*[class^="js-display-url"]').contains('product')
What the html is:
<span class="js-display-url">product/poss/newslanges</span>
But i want to match the class js-display-url starting with product but can't do that. please help.
With DOM selectors you cannot select elements based on the inner HTML, but you can loop through all the elements with that class and single out the ones that match your condition:
var allElements = document.querySelectorAll('*[class^="js-display-url"]');
var myElements = [];
for (var i = 0; i < allElements.length; i++) {
if (allElements[i].innerHTML.startsWith('product')) {
myElements.push(allElements[i]);
}
}
There isn't a DOM selector which will filter based on text nodes, but you can filter using some array methods, since a NodeList is array-like.
In particular, Array.prototype.filter can get the elements that meet your criteria.
var filter = Array.prototype.filter;
var allElements = document.querySelectorAll('.js-display-url');
var productElements = filter.call(allElements, function(element) {
return element.innerText.startsWith('product');
});
console.log(productElements);
<span class="js-display-url">product/poss/newslanges</span>
I am trying to get all the form elements within a specific div, and combine them into a single array using the array concat() method:
var div_id = 'some_div_id'; // in real life this is passed as a function parameter
var child_inputs = document.getElementById(div_id).getElementsByTagName('input');
var child_textareas = document.getElementById(div_id).getElementsByTagName('textarea');
var child_selects = document.getElementById(div_id).getElementsByTagName('select');
var field_elements = child_inputs.concat(child_textareas, child_selects); // this doesnt work?
However the script fails at the last line I'm not sure why. I can't use .childNodes because the div_id being passed is not the direct parent.
getElementsByTagName returns a NodeList not an array, so you can't use concat.
If you want to "transform" the nodeList into an array you could call slice from the Array protype chain:
var div_id = 'some_div_id',
divIdElement = document.getElementById(div_id); //cache the element
var getArrayFromTag = function(tagname) {
//get the NodeList and transform it into an array
return Array.prototype.slice.call(divIdElement.getElementsByTagName(tagname));
}
//Get the arrays
var child_inputs = getArrayFromTag('input');
var child_textareas = getArrayFromTag ('textarea');
var child_selects = getArrayFromTag ('select');
//use concat
var field_elements = child_inputs.concat(child_textareas, child_selects);
Those methods don't return an Array. Instead it's a NodeList or perhaps an HTMLCollection. (See the note under Syntax.)
You might loop over each nodelist and form an array of them 'by hand'.