Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

forEach callback does not execute with getElementsByClassName

In the below code,

<!DOCTYPE html>
<html>
    <head>
        <title>Hide odd rows</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <div style="background-color:#8F9779;width:200px;height:30px;">
        </div>
        <hr style="width:200px" align="left">
        <table border="1" >
            <tr class="hide" >
                <td width="40" height="20">row 1</td>
            </tr>
            <tr>
                <td width="40" height="20">row 2</td>
            </tr>
            <tr class="hide">
                <td width="40" height="20">row 3</td>
            </tr>
            <tr>
                <td width="40" height="20">row 4</td>
            </tr>
            <tr class="hide">
                <td width="40" height="20">row 5</td>
            </tr>
        </table><br>
        <button type="button" name="HideRows">Hide Odd Rows</button>
        <script type="text/javascript" src="hideOddRows.js"></script>
    </body>
</html>

/* hideOddRows.js */
document.querySelector('[name=HideRows]').onclick = hideRows;

function hideRows(){
    var elements = document.getElementsByClassName('hide');
    elements.forEach(function(element){
        element.style.visibility = "hidden";
    });
    return true;
}

As per debugging, callback function for each element of elements array is not executing on click event.

I consider elements as keyed collection, as shown below..

enter image description here

--

How to resolve this error?

like image 577
overexchange Avatar asked Dec 16 '15 04:12

overexchange


3 Answers

forEach is not included in the prototype of the array-like HTMLCollection object returned by getElementsByClassName.

An HTMLCollection instance is array-like, in that you can access elements by indexes, but it does not include all of the methods of an array, as you have discovered with forEach.

You can however manually call the method on the object by accessing the method from the Array prototype.

var elements = document.getElementsByClassName('hide');
Array.prototype.forEach.call(elements, function(element){
    element.style.visibility = "hidden";
});
like image 162
Alexander O'Mara Avatar answered Nov 03 '22 00:11

Alexander O'Mara


The forEach method is for arrays. It's not working because .getElementsByClassName() returns an HTMLCollection.

To work around this, use:

var elements = document.getElementsByClassName('hide');
Array.prototype.forEach.call(elements, function(element){
    element.style.visibility = "hidden";
});

or shorter:

var elements = document.getElementsByClassName('hide');
[].forEach.call(elements, function(element){
    element.style.visibility = "hidden";
});
like image 32
Josh Crozier Avatar answered Nov 03 '22 01:11

Josh Crozier


you can convert elements to an array and then call forEach().

 var elements = document.getElementsByClassName('hide');
 elements = Array.prototype.slice.call(elements,0);
    elements.forEach(function(element){
        element.style.visibility = "hidden";
    });

fiddle :https://jsfiddle.net/assx7hmh/

like image 1
Ramanlfc Avatar answered Nov 03 '22 02:11

Ramanlfc