DOM4 – query and queryAll

The DOM4 is coming with two brand new methods, query and queryAll.

Popular frameworks like jQuery, Dojo, and Prototype implemented a way to query elements on a web page in JavaScript using CSS selector. This way of traversing the DOM became so popular and useful that it made it into the standards with querySelector and querySelectorAll. But, those methods are not perfect and that is why we need query and queryAll.

The issue with querySelectorAll is that it does not return an array with the list of items, but a non-live NodeList, which is an array-like object. It only has the length property and a method called item that we can use to access the items in the nodelist. So, the nodelist does not have the same methods of the arrays. In order to illustrate the difference, let’s see an example.

querySelectorAll

We want to select all the paragraphs that have the className “demo” and change their color to red. With querySelectorAll, we can achieve our goal using a for loop because the list returned by querySelectorAll is really not an array. So, there are not methods inherited from the Array object.

var demo = document.querySelectorAll('p.demo');

for(var i = 0; i < demo.length; i++){
  demo[i].style.color = "red";
}

queryAll

DOM4 is coming with two brand new methods, query and queryAll. The differences with the previous methods is that they return an array instead a nodelist. This is very useful because the result can be manipulated with array methods like forEach, map, pop, etc. Let’s see the previous example, but using queryAll.

var demo = document.queryAll('p.demo');
demo.forEach(function(item){
 item.style.color = 'red';
});

As you can see, queryAll avoids the use of loops and gives a feeling of jQuery-like style to your scripts. Furthermore, it is less typing and more elegant than using a for loop.

Polyfills

At the time of this article, it is not implemented in any browser but you can start using the basic functionality by adding the following code into your scripts.

(function () {
   "use strict";

  if (!HTMLElement.prototype.queryAll) {
        HTMLElement.prototype.queryAll = document.queryAll = function (q){
         return Array.prototype.slice.call(this.querySelectorAll(q), 0);
      };
    }

   if (!HTMLElement.prototype.query) {
        HTMLElement.prototype.query = document.query = function (q){
         return this.queryAll(q)[0] || null;
      };
   }
}());

However, if you want a more detailed and careful implementation, you will need to go with a full polyfill. Here is a list of DOM4 polyfills in case you are interested.

Have your say