Combining arrays returned by getElementsByWhatever - javascript

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'.

Related

How to get value on class and put into array JavaScript DOM?

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;

Concat two nodelists

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.

Array of element of the same class javascript

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;
});

Better way to create arrays in javascript?

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());
});

putting source of all images into an array

What is the cleanest way to put the source attribute string of all images within a div into an array?
I was hoping this would work -
var imageSourceArray = $("#leDiv img").attr('src');
alert(imageSourceArray[3]); //not alerting the source, boo hoo.
Do I need to loop through $("#leDiv img") and add each src string to an array individually? Or is there a more elegant way to do this?
You can use jQuery's map function which is described as:
Pass each element in the current matched set through a function, producing a new jQuery object containing the return values.
For your example:
var mySources = $('#leDiv img').map(function() {
return $(this).attr('src');
}).get();
Edit: Far more elegant solution, there's obviously still some looping involved internally:
var img_sources = $('#leDiv img').map(function(){ return $(this).attr('src') });
You will in fact need to loop over the collection and add sources individually.
var img_sources = [];
$('#leDiv img').each(function(i,e){
img_sources.push($(e).attr('src'))
})
Some background: jQuery.fn.attr() maps to jQuery.access() internally, the key part of which looks like this:
function( elems, key, value, exec, fn, pass ) {
var length = elems.length;
// setter functions omitted here …
// Getting an attribute
return length ? fn( elems[0], key ) : undefined;
}
Note the elems[0] part – only the first item in the collection is fed to the subsequent callback function (jQuery.attr() in fact) responsible for extracting the information.
var imageSourceArray = [];
$('#leDiv img').each(function(){
var src = $(this).attr("src");
imageSourceArray.push(src);
});
alert(imageSourceArray[3]);
you already have the src in a collection when you fetch the the images. It may be more efficient to not store the src attributes in another array:
$('#leDiv img').each(function(i,e){
var dosomethingwith = $(e).attr('src');
})
or you could do:
var ImageCol = $('#leDiv img');
alert(ImageCol[3].attr('src'));

Categories