'forEach on querySelectorAll not working in recent Microsoft browsers
I am making a script for choices about a product (colors etc), which works in every browser except for Internet Explorer (11) & Edge.
I put the choices of each parameter in a array and apply a function to them with the array.forEach() method.
Example for the color parameter:
var color_btns = document.querySelectorAll('#color > p');
color_btns.forEach(function(color) {
color.onclick = function () {
color_btns.forEach(function(element) {
if (element.classList.contains('selected')) {
element.classList.remove('selected');
}
});
color.classList.add('selected');
document.querySelector('#f_color').value = color.dataset.id;
};
});
I get the following output in the console of both IE & Edge:
Object doesn't support property or method 'forEach'
After searching about the issue, I learnt that this function should be supported by IE 9 and newer. I tried to define the function by myself without success. When I log the function it is defined as a function (with "[native code]" inside).
I replaced every .forEach by a for and it's working pretty well,
- but how can I make it work ?
- Is there a specific usage of the
forEach()for Internet Explorer & Edge ?
I thought it was Array.prototype.forEach and that recent versions of IE (and all versions of Edge) had it...?
Solution 1:[1]
OK, let's start from here, in JavaScript, we have some cases which we call it Array-like, means even it looks like an array, it's not a real array...
For example arguments in function or in your case Nodelist...
Even All modern browsers understand which you'de like to change it to Array and work well, in IE and some other browsers it's not supported using array functions on Nodelist for example...
So if you supporting broad range of browsers, it's better to convert them to an array before doing any activity on them...
There are few ways to convert Array-like values to real Array...
One widely used in ES5 is this structure:
Array.prototype.slice.call(YourNodeList);
So you can do:
var allDivs = document.querySelectorAll("div");
var allRealDivsArray = Array.prototype.slice.call(allDivs);
But if you using ES6, there are even neater ways to do it, just make sure you convert them to ES5 using babel for example as those old browsers which not supporting looping over array-like, won't support ES6 as well for sure...
Two very common ways to do them are:
1) Using Array.from
const allDivs = document.querySelectorAll("div");
const allRealDivsArray = Array.from(allDivs);
2) Using [...Array]
const allDivs = document.querySelectorAll("div");
const allRealDivsArray = [...allDivs];
Solution 2:[2]
While it may look like an array, it's actually a NodeList which doesn't have the same features as an array. Use a for loop instead
color_btns = document.querySelectorAll('#color > p');
for (var i = 0; i < color_btns.length; i++) {
color_btns[i].onclick = function () {
for (var j = 0; j < color_btns.length; j++) {
if(color_btns[j].classList.contains('selected')) {
color_btns[j].classList.remove('selected');
}
}
color_btns[i].classList.add('selected');
document.querySelector('#f_color').value = color_btns[i].dataset.id;
};
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | T.J. Crowder |
