[dom] MutationObserver with querySelector for elements

zbraniecki has just created a new issue for 
https://github.com/whatwg/dom:

== MutationObserver with querySelector for elements ==
MutationObserver is a great tool for writing small libraries that 
operate on specific types of elements. 
Examples:

* Libraries that extend the behavior of particular element
** Date/Time pickers on `<input type="datetime">`
** Additional API on some types of `<link>` elements
* Libraries that modify custom elements (from outside extension of 
web-components)
* Libraries that modify elements with certain attributes:
** Libraries that aid with specific `aria-*` values
** Libraries that handle localization of `data-l10n-*` elements


Currently, MutationObserver API is designed to aid code that wants to 
operate on all subtree operations of a given root.
But in all those cases the basic premise is that they want to handle 
specific set of elements. Their additions/removals and possibly 
modifications.

The result is that in all those cases that I encountered in my work 
there's a massive amount of noise generated because the library is 
fishing for a particular element type, while it has to retrieve all 
node additions/removals and filter them out manually.

In many cases, the ratio of nodes inserted (dynamically or by the 
parser) to elements the library wants to operate on is 100/1.

My understanding is that the platform is in much better position to 
optimize filtering the elements for MutationObserver than anything 
that the MutationObserver callback can do.
Additionally, even if the code logic would be the same, the sole fact 
that the `mutations` argument has to be constructed and then the 
callback for them has to be called, for many mutations that are not 
relevant to the MutationObserver is a waste of CPU time and memory/GC 
allocation.

My initial proposal would look something like this:

```
const observerConfig = {
  attributes: true,
  attributeFilter: ['data-l10n-id', 'data-l10n-args'],
  childNodes: true,
  querySelector: '*[data-l10n-id], *[data-l10n-args]'
}; 

var mo = new MutationObserver(onMutations);
mo.observe(this.doc, observerConfig);

function onMutations(mutations) {
  const targets = new Set();
  const removedTargets = new Set();

  for (let mutation of mutations) {
    switch (mutation.type) {
      case 'attributes':
        targets.add(mutation.target);
        break;
      case 'childList':
        mutation.addedNodes.forEach(node => targets.add(node));
        mutation.removedNodes.forEach(node => 
removedTargets.add(node));
        break;
    }
  }

  translateElements(targets);
  cleanupAfterElements(removedTargets);
} 
```

See https://github.com/whatwg/dom/issues/77

Received on Friday, 18 September 2015 22:02:13 UTC