why document.getElementsByClassName("className") returns object - javascript

I have a some dom objects that are selected with :
var elems = document.getElementsByClassName("royal") ;
and also another objects
var collapsedElems = document.getElementsByClassName("collapsed");
my problem occured when i tried to concat elems and collapsedElems with array concat() method
elems.concat(collapsedElems)
but the return type of getElementsByClassName() is not array actually it is
object. I checked it at chrome console with typeof operator. that seems weird to me how can i combine this two group of object. ?

getElementsByClassName() returns an HTMLcollection object which is similar to an array but not really an array so you can't call array methods using the returned value.
One hack is to use Array's prorotype methods along with .call()/.apply() to pass the returned object as the context.
var elems = document.getElementsByClassName("royal") ;
var collapsedElems = document.getElementsByClassName("collapsed");
var earray = Array.prototype.slice.call(elems, 0);
var concatenated = earray.concat.apply(earray, collapsedElems) ;
console.log(concatenated)
Demo: Fiddle

It returns an HTML Collection which does things that arrays do not (such as getting live updates when the DOM changes).
If you want to get an array with elements from both collections in it, then you could:
Create an array and then populate it by looping over each of the collections and pushing each member into it (which will give you an array) or
Use document.querySelectorAll(".royal, .collapsed"); (gets a NodeList)

From the MDN:
Returns an array-like object of all child elements which have all of
the given class names. When called on the document object, the complete
document is searched, including the root node. You may also call
getElementsByClassName() on any element; it will return only elements
which are descendants of the specified root element with the given
class names.
You can try this:
function getElementsByClassName(className)
{
if (document.getElementsByClassName)
{
return document.getElementsByClassName(className);
}
else
{
return document.querySelectorAll('.' + className);
}
}

Related

How do I extract data from this NodeList?

I need to extract a particular data property from a NodeList. I have no problems getting data from arrays or objects in general, but this NodeList is beyond me! It doesn't work even if I use Array.from() to turn it into an array.
This is the relevant code:
And this is what it logs:
In the log on line 173, the closed arrays contain all the data I need, but I simply don't understand how to go there. When I try to go to an index there it just opens up the path coordinates.
I will also add the code image as text, it doesn't have any lines though:
let test = d3.selectAll(".unit")
console.log(test)
console.log(test._groups)
console.log(test._groups[0])
console.log(test._groups[0][0])
EDIT: To be more specific, the data I need is a "data" property inside the array below the nodelist (?), compare to the previous image of the log on line 173:
EDIT2: To be even more clear: When I open the nodelist in the console, I also get an array, and it is only the array that interests me. I don't understand this data structure, how the array is related to the nodelist, but I have tried to access the indexes of the array in a variety of ways and nothing has worked.
NodeList objects are collections of nodes. In some cases, the NodeList is live, which means that changes in the DOM automatically update the collection.
In other cases, the NodeList is static, where any changes in the DOM does not affect the content of the collection. The document.querySelectorAll() method returns a static NodeList, for instance.
It's possible to loop over the items in a NodeList using a for loop:
for (let i = 0; i < myNodeList.length; i++) {
let item = myNodeList[i];
}
for...of loops will loop over NodeList objects correctly:
const list = document.querySelectorAll('input[type=checkbox]');
for (let checkbox of list) {
checkbox.checked = true;
}
You can use item() method to get an item by its index. For instance, this is how you can get id of the first <div> on some page:
document.querySelectorAll("div").item(0).id
In your case, you have an array and it contains an element of type NodeList.
So, when you do test._groups[0] you get the first element of your array and this element is NodeList and you need to work with it as with NodeList (see above)! For instance:
const arr = [1,2]; // simple array
// arr[0] is 1.
// in your case you have an array, but elements in that array are of type NodeList
// (that's why console shows something like [NodeList(...)])
// when you get something from your array - it will be NodeList
// hence you can iterate over it or get some particular item like
test._groups[0].item(0).ariaAtomic
There are a lot more useful methods. Check docs for more details.
To extrat data from nodeList you must loop your node list and the stock nodList elemnts in otheer tab
var list = node.childNodes;
// Using for..of
for(var value of list.values()) {
console.log(value);
}
[check this link https://developer.mozilla.org/en-US/docs/Web/API/NodeList/values][1]
NodeList objects are collections of nodes.
You can loop through a node list by using the NodeList.length property and read the innerHTML of it as follows.
And refer the document for more knowlege
var items = document.getElementsByTagName("p");
var gross = "";
for (var i = 0; i < items.length; i++) {
gross += items[i].innerHTML;
}
and also you can loop through the

Populating a linear array with DOM Nodes by recursion in JavaScript

I am trying to make a functional recursion function for recursive DOM querying in JavaScript, here is my current attempt
//function to take a root DOM object and use a supplied query to return all the objects below that
function recurseTree(root, query, nodeList ) {
//run an initial query
let allNodes = root.querySelectorAll(query);
if (!allNodes.length) {
return [];
}
allNodes.forEach(function(node) {
return Array.from(allNodes).concat(recurseTree(node, query, nodeList));
});
}
I set up and call the function like so:
var ulList = [];
//calling recursive function to populate the list with all children that fit query
ulList = recurseTree(nav_root, "a + ul", ulList);
What is so bewildering to me is that whilst the array fed in (ulList) never deviates from an empty array when stepping through in debugger it actually sets ulList to undefined afterwards, as I try to print it to console afterwards
First the querySelectorAll function is already finding element in tree that match the selector. So your recursive function make no sense.
If you want to get a flat array of a NodeList you can do: (but you already know)
Old School
Array.prototype.slice.call(root.querySelectorAll(query))
Supported way
Array.from(root.querySelectorAll(query))
ES6
[...root.querySelectorAll(query)]

Function filter() in jquery

I study jquery, but i have a little confusion about this code :
var list = mylist.filter(function(f) {
return $(f)
.find('.anthing')
.length > 0;
});
what does $(f) mean?
Your mylist is an array or array like object. The f in the parameters is the single item in your myList.It calls the function for every item in the myList.Then it wraps your f into jQuery object and then the .find() will be visible on your object
It is the index passed through the function, which indicates the
0-based position of the element within the unfiltered set of matched
elements.
In your case $(f) is useless since it represent $(0) || $(1) which does not represent a selection.

Cannot push element to array after using querySelectorAll

So I have a simple class with few properties. Using prototyping I add few methods.These methods returns this, so I could chain tham together.
Get method finds all elements and puts into allCurrentElements, which is an array (or at least I think so). And when I use CreateElement method, it simply creates element and tries to push it to existing array allCurrentElements.
To use it, simply write var a = _h.Get('p').CreateElement('div'). And here is where I get an error Uncaught TypeError: this.allCurrentElements.push is not a function(…).
If I try to assign newly created element using index it does not throw error however, this element does not appear in the array.
var _h = (function(){
var Helper = function(){
this.allCurrentElements = [];
}
Helper.prototype.Get = function(query){
this.allCurrentElements = document.querySelectorAll(query);
return this;
}
Helper.prototype.CreateElement = function(el, attr) {
var elem = document.createElement(el);
for (var a in attr) {
elem[a] = attr[a];
}
//this.allCurrentElements[this.allCurrentElements.length] = elem;
this.allCurrentElements.push(elem);
return this;
}
return new Helper();
})();
https://jsfiddle.net/Ldp58onu/
You have to check Document.querySelectorAll() documentation https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
Returns a non-live NodeList of all the matching element nodes.
NodeList are used very much like arrays and it's tempting to invoke Array.prototype methods on them, however NodeList objects don't have any of the familiar Array methods.
So you have to iterate through NodeList something like :
Array.prototype.forEach.call(document.querySelectorAll(query), function(element){
allCurrentElements.push(element);
});
document.querySelectorAll() returns NodeList which is an Array-like object.
The problem is that NodeLists are read-only. You'd need to transform it in an array. Array.prototype.slice.call(document.querySelectorAll(query));
after that you'll be able to whatever you want.

jquery exclude array elements

I have an array of elements which I want to maintain efficiently, adding and removing arrays of elements over time.
var myElements = $('.initial');
jquery's merge() seems perfect for adding items as it doesn't create a new array and just adds to the existing one:
$.merge(myElements, $('.to-add'));
Is there an equivalent for removing, that also modifies the array in-place? Something like:
$.exclude(myElements, $('.to-remove'));
I do actually have arrays of DOM elements, and the selectors are just used as examples.
Assuming that you're after the relative complement of b in a.
And you don't want to create additional objects while process.
The function is for both plain Array and jQuery set.
(thus used $.each, $.inArray instead of Array.prototype.forEach Array.prototype.indexOf)
I wrote a function that fits your requirement.
$.exclude = function(a,b) {
var idx;
$.each(b, function(i, val) {
while((idx = $.inArray(val, a)) !== -1) {
a.splice(idx, 1);
}
})
return a;
}
test this code here
https://jsfiddle.net/happyhj/uwd4L1dm/8/
and you can use like this.
$.exclude(myElements, $('.to-remove'));
use jquery not method,
var filtered = $(myElements).not($('.to-remove'));
You can use delete to remove an element from an array and then use $.grep to remove the empty space.
//[0] since $("#id") will be a jquery Object
//[0] will return the particular DOM element
var orgArray = [$("#merge1")[0],$("#merge2")[0],$("#merge3")[0]];
var secArray = [$("#merge4")[0],$("#merge5")[0]]
// Will merge other two values;
// jQuery merge will merge contents of
//two array into first array
var merArray = $.merge(secArray, orgArray);
// Want to remove $("#merge2");
var getIndex = merArray.indexOf($("#merge2")[0]);
if(getIndex >-1){
delete merArray[getIndex]
}
// length before filtering
$("#l1").text(merArray.length);
//Now will remove Empty Space
merArray = $.grep(merArray,function(n){
return n==0 || n
});
$("#l2").text(merArray.length);
JSFIDDLE
You are using methods that are meant for array literals. jQuery already has method add() which will return a modified jQuery object that includes the elements matching the selector
var myElements = $('.initial');
var newCollection = myElements.add('.to-add');
newCollection.not('.to-remove').doSomething();
Don't think of jQuery objects as arrays although they are array like.
Reference add()
It's not clear what your overall objective really is but most likely you can manage it with any number of filtering methods that already exist within the api

Categories