Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
(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?)
@milgner

Ha, this is brilliant in its simplicity! Thank you very much! I was just starting to tear my hair because the result from a querySelectorAll() call didn't support forEach.

@DavidBruant
Owner

Actually, now, I would have a completely different advice which is to turn every NodeCollection/HTMLCollection to an actuall array.
Something like:
function $$(selector){
return Array.prototype.slice.call(document.querySelectorAll(selector), 0);
}

@milgner

Thanks for the feedback. I'll keep that in mind but currently a forEach method is all I need.

@issam-chouchane

Try

    var querycollection = WinJS.Utilities.query(".className_1", document);
    querycollection.forEach(function (e) {
        // do some stuff with 'e'
        consol.log(e);
    });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.