I am trying to concat two nodelists using
var ul = document.querySelector("ul");
var down = document.getElementsByClassName("mobile")[0];
var ul_child = Array.prototype.concat.call(ul.children,down.children);
But this returns only two nodes from ul nodelist and ignore others. What is the most valid to concat two nodelsits? I would like to avoid brute looping them
Why don't you use one selector to select them at the same time than you do not need to concat them and you end up with an HTML Collection instead of an Array.
var elems = document.querySelectorAll("ul > li, .mobile > *");
console.log(elems);
<ul><li>x</li></ul>
<div class="mobile">y</div>
Set() ensures items are unique and the ES6 Spread operator makes it neat & tidy:
var elems = new Set([
...document.querySelectorAll(query1),
...document.querySelectorAll(query2)
]);
This is a bit of a different approach, but perhaps you could try combining them in your query selector:
var ul_down = document.querySelectorAll("ul,.mobile:first-child");
You can try converting the two NodeList objects to arrays first. Then calling concat on the results:
// Convert the first list to an array
var ul_list = document.querySelector("ul"),
ul_children_array = Array.prototype.slice.call(ul_list.children);
// Convert the second list to an array
var down_list = document.getElementsByClassName("mobile")[0],
down_children_array = Array.prototype.slice.call(down_list.children);
var ul_child_array = Array.prototype.concat.call(ul_children_array, down_children_array);
Ok, I guess that the spread operator was pretty new, when this question was posted.
But it is possible to do it this way also
const list1 = document.querySelectorAll(".some-selector")
const list2 = document.querySelectorAll(".some-other-selector")
const filters = Array.prototype.concat.call(...list1 , ...list2 )
And yet another approach:
document.querySelectorAll([".foo", ".bar"])
Will return a normal NodeList with all of the above matching, in the order in which they are found in the DOM.
Related
I have some tables that have data and can using it on <td>. So more like it I have something like this (show on images below)
My Element
I want to get that all positions Name and put it into an array so I can make of use that array I tried to use this code and got undefined
script.js
/** Checking if There positions name */
function checkPositions(){
let positions = document.getElementsByClassName('check-positions').innerHTML;
let array = [];
array.push(positions);
console.log(array);
}
Then how can I get that value??
The problem that you have is that document.getElementsByClassName('check-positions') returns a HTMLCollection which does not have an innerHTML property.
What you need to do is convert the HTMLCollection into an array, and then read the innerHTML property for each of the items in the array. See the following example:
const elements = document.getElementsByClassName('check-positions');
const positions = Array.from(elements).map(element => element.innerHTML);
console.log(positions);
<div class="check-positions">1</div>
<div class="check-positions">2</div>
<div class="check-positions">3</div>
Use like this
let positions = document.getElementsByClassName('check-positions')[0].innerHTML;
It's showing none because u r fatching whole array and pushing it without using indexes
Code
function checkPositions(){
all_ele = document.getElementsByClassName('check-positions')
length = all_ele.length
let array = [];
for( let i=0;i<length;i++)
{
let positions = document.getElementsByClassName('check-positions')[i].innerHTML;
array.push(positions);
}
console.log(array);
you can use jquery code to do this.
var arr = [];
$("#tablePlacement tr").each(function() {
var name = $(this).children('td.check-positions').text();
arr.push(name);
});
You should use
let positions = document.getElementsByClassName('check-positions').innerText;
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')
Hey guys need a bit of help here.
I'm trying to find all class names that start with the same naming convention in the DOM and put them all in to an array.
so for example.
<div class="userName_342">John</div>
<div class="userName_366">Doe</div>
<div class="userName_234">Bob</div>
<div class="userName_873">David</div>
I need help making the above code with a little bit of JavaScript to the array below.
var classArr = ["userName_342","userName_366","userName_234","userName_873"];
Any help on how to even get started would be greatly appreciated.
Thank you.
Assuming the relevant class is always the only class on those elements, you can do it with an "attribute starts with" selector combined with Array#map:
var list = document.querySelectorAll("div[class^=userName_]");
var classArr = Array.prototype.map.call(list, function(div) {
return div.className;
});
Matt Burland points out that that will return an array with duplicate entries if there are multiple elements with the same class. Two ways to address that:
Array#reduce, but this use of it isn't very efficient:
var list = document.querySelectorAll("div[class^=userName_]");
var classArr = Array.prototype.reduce.call(list, function(array, div) {
if (array.indexOf(div.className) === -1) {
array.push(div.className);
};
return array;
}, []);
...or using a temporary map:
var list = document.querySelectorAll("div[class^=userName_]");
var map = {};
Array.prototype.forEach.call(list, function(div) {
map[div.className] = true;
});
var classArr = Object.keys(map);
Array#map, Array#reduce, Array#forEach, and Object.keys are all ES5 features, but if you need to support older engines, they can all be shimmed.
querySelectorAll is available on all modern browsers, and IE8.
Here is an example of a function to find based on class name.
http://codepen.io/justindunham/pen/nhJsD
document['getElementsByRegex'] = function(pattern){
var arrElements = []; // to accumulate matching elements
var re = new RegExp(pattern); // the regex to match with
function findRecursively(aNode) { // recursive function to traverse DOM
//console.log(aNode);
if (!aNode)
return;
if (aNode.className !== undefined && aNode.className.search(re) != -1)
arrElements.push(aNode); // FOUND ONE!
for (var idx in aNode.childNodes) // search children...
findRecursively(aNode.childNodes[idx]);
};
findRecursively(document); // initiate recursive matching
return arrElements; // return matching elements
};
Based fully on this answer
Select div using wildcard ID
I'm trying to create an array in Javascript with a size that is equivalent to the number of times a certain class is found in the DOM, and then iterate through it to grab the text from an input field present in that class. I can easily do this like so:
var count = 0;
$('.className').each(function() {
count++;
});
var classes = new Array(count);
count = 0;
$('.className input[type=text]').each(function() {
classes[count++] = $(this).val();
});
This looks like a lot of code for what seems to be a relatively simple task. Is there a more efficient or less lengthy way of doing this?
Thanks
It looks like you want this :
var classes = $('.className input[type=text]').map(function(){
return this.value
}).get();
But it's a guess : it's not clear why you start by counting all elements of the class and then iterate on the inputs.
You can construct an array of elements directly from your selector via the makeArray function, then transform the result using a map.
var classes = $.makeArray($('.className input[type=text]')).map(function() {
return $(this).val();
});
Use jQuery's map function, then get if you need a pure array:
var values = $('.className input[type=text]').map(function() {
return $(this).val();
}).get();
each passes the index, so you don't need to do it yourself:
var classes = [];
$('.className input[type=text]').each(function(index, value) {
classes[index] = $(this).val();
});
Arrays are dynamic and therefore don't need to be initialized. Create a new array, loop through the inputs and push the values to the new array:
var classes = [];
$('.className input[type=text]').each(function(idx, elem) {
classes.push($(elem).val());
});
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'.