Combining Multiple NodeLists in Javascript

Initially, I was seeking a sophisticated method to replicate the functionality of Array.concat() on the results of the getElementsByTagName function in older browsers like IE because it appeared that concat wasn't supported. However, as it turns out, the reason the returned object didn't support it is because it's not actually an Array. Whoops!

The truth is, getElementsByTagName returns a NodeList. So, the real question becomes: what's the best approach to obtain a single list containing all form elements in a document (input, select, textarea, button) for looping through them? It doesn't necessarily have to be an array... a single NodeList would also work perfectly.

Please keep in mind that I'm working with IE6 for a corporate intranet system (soon upgrading to IE8).

My solution eventually ended up being:

  • It turned out to be more straightforward and likely more efficient to encapsulate the code into a separate function and call it three times with the different nodelists rather than attempting to merge them together.

  • In the end, I switched over to using MooTools (after spending hours researching various frameworks). Now, obtaining an array of desired items is incredibly simple. I suggest utilizing a JavaScript framework like this instead of struggling to find the optimal approach yourself. Of course, I value learning the raw language (which is why I hesitated to use a framework for so long), but sometimes, the quickest way to achieve results is just as important in a business setting as improving one's proficiency with the language.

Update: Nearly two years later, I'd simply opt for jQuery and call it a day!

Answer №1

When combining nodelists, you can first convert them into arrays using Array.prototype.slice.call and then concatenate them in a regular manner.

var a = Array.prototype.slice.call(document.getElementsByTagName("p")),
    b = Array.prototype.slice.call(document.getElementsByTagName("div"))

var c = a.concat(b);

Update: (In response to your comment)

If you only have a few types of elements, this method works fine. However, as you increase the number of DOM calls, performance may decrease. It is advisable to use

document.getElementsByTagName('*')
, iterate through the list, and select the elements with the required nodeName.

Additionally, note that the Array.prototype.slice method might not be compatible with all browsers. Refer to line#723 in the comments section of sizzle.js for more information (this file is the selector engine used by jQuery).

For a simpler approach, consider using a library like jQuery which handles these complexities for you. You can achieve the same result with:

$("input, select, textarea, <other tags>")

Answer №2

Utilizing the spread operator in ES6 opens up new possibilities.

const mergedArrays = [...array1, ...array2];

Answer №3

function combineElements(list1, list2) {
  var slice = Array.prototype.slice;
  return slice.call(list1).concat(slice.call(list2));
}

console.log( combineElements( inputs, selects ) ); // => [input, select]

Answer №4

According to information found in the MDN Documentation, an alternative method is using Array.from to transform a NodeList into an Array for browsers that have support for it.

Answer №5

let elementsDiv=document.getElementsByTagName('div'),
elementsButton=document.getElementsByTagName('button');
elementsDiv=[].slice.call(elementsDiv, 0,elementsDiv.length).concat([].slice.call(elementsButton, 0,elementsButton.length))

Answer №6

It surprises me that there are not more answers on this topic, but I decided to give it a try and came up with the following function despite having to struggle a bit.

function filterElementsByTags(element, tags) {
   var elements = element.getElementsByTagName('*');
   var filteredElements  = [];
   for (var i = 0; i < elements.length; ++i ) {
      if (tags.includes(elements[i].nodeName.toLowerCase())) {
         filteredElements.push(elements[i]);
      }
   }
   return filteredElements;
}

var formElement = document.getElementById('form');
var selectedTags = ['input', 'select'];
console.log(filterElementsByTags(formElement, selectedTags));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

An issue has occurred while trying to execute the npm start command within PhpStorm

When I try to run npm start on Windows' command prompt, it works fine. However, I encounter errors when running it in the PhpStorm Terminal. You can see the errors here. Is this a result of them being different platforms or could it be related to som ...

jqGrid and the use of prototype functions

When using prototype functions in my code, I encounter an issue where adding a select box to the jqgrid results in an extra option being added at the bottom with a value that is a function. However, when I remove the prototype functions, everything works a ...

What is the best way to combine async/await with a custom Promise class implementation?

I've created a unique Promise class. How can I incorporate it with async/await? type Resolve<T> = (x: T | PromiseLike<T>) => void type Reject = (reason?: any) => void class CustomizedPromise<T> extends Promise<T> { ...

How to append double zeros to a number in Material UI Data Grid

I'm currently working on a React.js application that utilizes the DataGrid component from the Material UI (MUI) library to display data. My challenge lies in formatting full numbers with trailing zeroes for better clarity. For example, displaying 625 ...

Forwarding refs in React FC allows you to easily pass down

I have encountered an issue with references - I am trying to reference a function component and pass props to it. Currently, I have my Parent component and Child Component set up. In the parent component, I need to use a ref to access my child component. S ...

What is the best way to retrieve an object instead of an array?

When attempting to retrieve a JSON Object, I unexpectedly received an array instead. My query is based on the primary key, so I anticipate only one result. This is my current method : router.get("/student_info/:id", (req, res, next) => { connecti ...

What is the best way to auto-fill input fields with data from a Json file

My goal is to automatically populate HTML form fields based on user selection. I have obtained code for related functions, such as fetching JSON data and creating dropdown lists, from a friend. Here is the link to that code: https://jsfiddle.net/r4zuy7tn/1 ...

IE causing Ul LI Menu to not display as Block

I'm encountering an issue with my menu. It displays correctly in Firefox and Chrome, but in IE8 it appears as a vertical list instead of a horizontal menu. I have included a doctype and I am linking to the HTML5 JavaScript via Google, so I'm not ...

What is the best way to include multiple views in a main HTML template in Angular?

Is there a way to load two HTML files into a base HTML file? Essentially, I have a base HTML file with a header and content view, and I want to load different HTML files into each of them. Here is the base HTML file structure: <div class="container"> ...

Error Message: A key is being provided to the classes property that is not implemented in the current context

Trying to customize Material-UI styles with makeStyles() as outlined in the documentation but encountering a warning when passing a classname in the parent component that is not specified in useStyles. The warning message reads: Warning: Material-UI: th ...

Can one showcase a php content using an ajax event?

I’m having trouble asking the right question because I’m not sure what I’m doing. I have a form that includes a default PHP script that creates three different lines: <form method="GET" name="NewDeliveryNote" action="ItemPosts_INSERT.php"> < ...

Loop through the ng-repeat scope object in AngularJS

Is it possible to create rows of 3 using bootstrap and ng-repeat with data from a scope object without the loop repeating every three times due to ng-if? I am curious if something like <h4> {{yogurt[$index+1].name}} </h4> would work. Below is ...

granting authorization to modify content post channel establishment in discord using discord.js

I am encountering an issue with granting the message.author and staff permission to view the channel right after its creation. The problem arises when the channel's parent (category) is changed, causing it to synchronize with the permissions of the pa ...

Utilize jQuery Function on Identical Class of <ul> Elements

I have integrated a listview control in my ASPX page. The data is being fetched from the database and displayed in the listview. I have also utilized jQuery script to implement the .fadein() and .fadeout() effects on the listview elements. However, when I ...

Bidirectional binding in Angular 2 Custom Directive

I've been working on a custom directive that automatically selects all options when the user chooses "All" from a dropdown. While I was able to get my custom directive to select all options, it doesn't update the model on the consuming component. ...

What is the process for including a scope in an Angular.js HTTP controller?

I am looking to access a $scope variable within this controller in order to utilize Angular functions like ng-click and ng-change in my HTML. Currently, I am only able to use the $http function but unable to execute any Angular methods on it. I am struggli ...

Using a Vue component to send a form for submitting data into the backend database of a Django application

Where should the connection between a form within a Vue component and a Django backend be established? In my frontend, I am utilizing VueJS where my primary component can retrieve data from a JSON file through an API specified in my Django view and URL fi ...

Tips for successfully retrieving a boolean value from an ASP.Net JavaScript AJAX request using a C# method

Query: Is there a way to call a C# function from JavaScript code on an .aspx webpage to get authentication results based on a username and password? Here is the JavaScript AJAX POST request I am currently using: $.ajax({ type: "POST", ...

jQuery - delete a single word that is case-sensitive

Is there a way to eliminate a specific case-sensitive word from a fully loaded webpage? The word in question is "Posts" and it appears within a div called #pd_top_rated_holder that is generated by Javascript. The Javascript code is sourced externally, so ...

Dynamic text displayed on an image with hover effect using JavaScript

Currently, I am in the process of developing a website for a coding course that is part of my university curriculum. The project specifications require the use of JavaScript, so I have incorporated it to display text over images when they are hovered over ...