Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is NodeList live and when is it static?

From MDN for NodeList:

In some cases, the NodeList is a live collection, which means that changes in the DOM are reflected in the collection. For example, Node.childNodes is live:

 var parent = document.getElementById('parent');  var child_nodes = parent.childNodes;  console.log(child_nodes.length); // let's assume "2"  parent.appendChild(document.createElement('div'));  console.log(child_nodes.length); // should output "3" 

In other cases, the NodeList is a static collection, meaning any subsequent change in the DOM does not affect the content of the collection. document.querySelectorAll returns a static NodeList.

So .... kind of annoying! Is there any central reference for which methods return live lists and which ones return static lists, without having to check individually for all the various parts of the DOM API? Is there any rule at work here?

like image 525
temporary_user_name Avatar asked Jan 27 '15 04:01

temporary_user_name


People also ask

What is static NodeList?

In other cases, the NodeList is a static collection, meaning any subsequent change in the DOM does not affect the content of the collection. document. querySelectorAll returns a static NodeList. So ....

Is querySelector live or static?

Well since querySelector does not return a list, it's static.

What is a live HTMLCollection?

A live is: when the changes in the DOM are reflected in the collection. The content suffers the change when a node is modified. A Not Live is : when any change in the DOM does not affect the content of the collection. document. getElementsByClassName() is an HTMLCollection, and is live.

What is the difference between NodeList and HTMLCollection?

The Difference Between an HTMLCollection and a NodeList The index starts at 0. Both have a length property that returns the number of elements in the list (collection). An HTMLCollection is a collection of document elements. A NodeList is a collection of document nodes (element nodes, attribute nodes, and text nodes).


2 Answers

Information about each method details if it is live or not, but there does not seem to be a standard convention for determining it.

document.getElementsByClassName() is an HTMLCollection, and is live.

document.getElementsByTagName() is an HTMLCollection, and is live.

document.getElementsByName() is a NodeList and is live.

document.querySelectorAll() is a NodeList and is not live.

HTMLCollections appear to always be live

An HTMLCollection is a list of nodes. An individual node may be accessed by either ordinal index or the node's name or id attributes.

Note: Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.

http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-75708506

So, HTML Collections are always "in the dom," whereas a nodeList is a more generic construct that may or may not be in the DOM.

A NodeList object is a collection of nodes... The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.

http://www.w3.org/TR/DOM-Level-3-Core/core.html#td-live

Sounds good, right?

A collection is an object that represents a lists of DOM nodes. A collection can be either live or static. Unless otherwise stated, a collection must be live.

http://www.w3.org/TR/2012/WD-dom-20120405/#collections

So static collections will be indicated as such in the spec. So, by this logic, document.querySelectorAll() is a collection, but it is not in the DOM. Because while collections may or may not be live, collections in the DOM must be live... This distinction is not super helpful.

Well, here is a quick method to determine if a collection is live; it appends a clone of a member of the collection to the DOM (so it will match the selector), and checks to see if the length changed, and then removes it (so the page is not affected)

DEMO

function isLive(collection) {     if (HTMLCollection.prototype.isPrototypeOf(collection)) return true // HTMLCollections are always live      const length = collection.length;     if (!length) return undefined; // Inconclusive      const el = collection.item(0);     const parent = el.parentNode;     const clone = el.cloneNode();      clone.style.setProperty('display', 'none', 'important');     parent.appendChild(clone);      const live = collection.length !== length;     parent.removeChild(clone);     return live; }  const divs1 = document.getElementsByClassName('c'); const divs2 = document.getElementsByTagName('span'); const divs3 = document.getElementsByName('notFound'); const divs4 = document.querySelectorAll('.c');  console.log("document.getElementsByClassName('c'):", divs1.toString()); //   [object HTMLCollection] console.log("document.getElementsByTagName('notFound'):", divs2.toString()); //  [object HTMLCollection] console.log("document.getElementsByName('notFound'):", divs3.toString()); // [object NodeList] console.log("document.querySelectorAll('.c'):", divs4.toString()); //        [object NodeList]  console.log('isLive(divs1)', isLive(divs1)); // true console.log('isLive(divs2)', isLive(divs2)); // true console.log('isLive(divs3)', isLive(divs3)); // undefined console.log('isLive(divs4)', isLive(divs4)); // false
<html>     <body>         <div>             <div class="c">C1</div>             <div class="c">C2</div>         </div>         <div>             <div class="c">C3</div>             <div class="c">C4</div>         </div>     </body> </html>
like image 162
chiliNUT Avatar answered Oct 13 '22 19:10

chiliNUT


I don't know if there's a central reference, but these are the methods and properties I know of that return HTMLCollections and live NodeLists:

Methods

  • parentNode.getElementsByClassName() - returns an HTMLCollection
  • parentNode.getElementsByTagName()   - returns an HTMLCollection
  • parentNode.getElementsByTagNameNS() - returns an HTMLCollection
  •   document.getElementsByName()      - returns a NodeList

Properties

  • parentNode.children   - returns an HTMLCollection
  •       Node.childNodes - returns a NodeList
like image 42
Barmar Avatar answered Oct 13 '22 20:10

Barmar