Skip to content

Instantly share code, notes, and snippets.

@DavidBruant
Created June 9, 2011 03:41
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidBruant/1016007 to your computer and use it in GitHub Desktop.
Save DavidBruant/1016007 to your computer and use it in GitHub Desktop.
(document.querySelectorAll('*')).forEach ?
var els = document.querySelectorAll('a');
els.forEach(function(e){console.log(e.href);}); // TypeError: els.forEach is not a function
// Why?
// document.querySelectorAll returns a NodeList.
// First thing first, as opposed to other NodeList, this one is not live, mostly because the
// implementation of a live object would be terribly complicated for some selectors
// NodeList are a DOM interface introduced in DOM core level 1 (random guess)
// The ECMAScript binding (http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html) defines
// NodeList as objects. Unfortunately, the spec is not very accurate in how this object should be
// implemented. It does not say if things are inherited or not, no word on NodeList.prototype
// The de-facto standard is apparently that the protoype chain looks roughly like:
// myNodeList -> NodeList.prototype -> Object.prototype
// As you can notice, Array.prototype is not here. It has to be noted that at the time NodeList were
// invented + standardized was before/at the time of ECMAScript 3.
// At this time, Array.prototype only had:
// .concat, .join, .pop, .push, .reverse, .shift, .slice, .sort, .splice, .unshift
// Most of these methods are not applicable to NodeList since they either write on the NodeList.
// .forEach, .filter, etc. came later on with ECMAScript 5 but it was too late to consider adding
// Array.prototype on the prototype chain (is it really too late?)
// A workaround: on FF4 and Chrome, I have been able to have the following running:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style>
html, body {
margin:0;
padding:0;
}
td {
width:100px;
height:100px;
background-color:purple;
}
</style>
<script type="text/javascript">
NodeList.prototype.forEach = Array.prototype.forEach;
HTMLCollection.prototype.forEach = Array.prototype.forEach; // Because of https://bugzilla.mozilla.org/show_bug.cgi?id=14869
function randomColorString(){
var r, g, b;
r = Math.floor(256*Math.random()).toString(10);
g = Math.floor(256*Math.random()).toString(10);
b = Math.floor(256*Math.random()).toString(10);
return ('rgb('+ r +','+ g +','+ b +')');
}
function createTable(row, col){
var t = document.createElement('table');
var r,c;
var i,j;
for(i=0 ; i<row; i++){
r = document.createElement('tr');
for(j=0; j<col ; j++){
c = document.createElement('td');
r.appendChild(c);
}
t.appendChild(r);
}
return t;
}
function windowLoad(){
var table = createTable(6, 10);
document.body.appendChild(table);
var cells = document.getElementsByTagName('td');
cells.forEach(function(e,i,a){
e.style.backgroundColor = randomColorString();
});
}
window.addEventListener("load", windowLoad, false);
</script>
<title> TITLE </title>
</head>
<body>
</body>
</html>
// THE END !
// ... wait a minute
// Apparently, this doesn't work with document.querySelectorAll on FF4. I'll have to dig into that.
// THE END (until progress is made in the direction of DOM ECMAScript binding?)
@issam-chouchane
Copy link

Try

    var querycollection = WinJS.Utilities.query(".className_1", document);
    querycollection.forEach(function (e) {
        // do some stuff with 'e'
        consol.log(e);
    });

Copy link

ghost commented Sep 15, 2016

I use

[].forEach.call( querycollection, function(element_value, index_key){
console.log(element_value);
} );

But i'm looking for some library, maybe someone knows more perfect way to fix with library? Does Array.prototype.slice.call() work for every browser?

@ivandanielvillegasrojas

I have modified and used this:

(function() {
    if (typeof NodeList.prototype.forEach === "undefined") {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }

    if (typeof HTMLCollection.prototype.forEach === "undefined") {
        HTMLCollection.prototype.forEach = Array.prototype.forEach;
    }
})();

thank you!!

@vinyll
Copy link

vinyll commented Jan 31, 2018

Or you could use Array.from(document.querySelectorAll('a'))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment