16

getElementsByTagName() has 2 great features: it is fast and it is live. But what if I want to get p strong. Of course I could refine a selection using getElementsByTagName() again but wouldn't I lose the live effect for the new p tags?

Is there a way to turn querySelectorAll into a live selector?

Or... is there a way to use getElementsByTagName() and getElementsByClassName() to create a function that works in a similar way (at least with descendants) as querySelectorAll but being live?

Vandervals
  • 5,774
  • 6
  • 48
  • 94
  • 3
    Such a feature, if implemented natively, would probably be excluded from the dynamic profile, preventing level 4 selectors like `:has()` with complex selectors from being used, as live selector matching is basically what happens in CSS and as such is performance-sensitive. Still, I'm curious to know. – BoltClock Jun 01 '15 at 16:42

2 Answers2

13

Consider using mutation observers. Watch for childList with subtree: true. When the notification arrives, you can examine each added node with matches to see if it matches some selector.

function querySelectorAllLive(element, selector) {

  // Initialize results with current nodes.
  var result = Array.prototype.slice.call(element.querySelectorAll(selector));

  // Create observer instance.
  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      [].forEach.call(mutation.addedNodes, function(node) {
        if (node.nodeType === Node.ELEMENT_NODE && node.matches(selector)) {
          result.push(node);
        }
      });
    });
  });

  // Set up observer.
  observer.observe(element, { childList: true, subtree: true });

  return result;
}
  • this is looking good but I'm getting an error on target.matches. Did you try this? I just created a pen: http://codepen.io/vandervals/pen/Nqpxww?editors=101 – Vandervals Jun 02 '15 at 13:52
  • Sorry, it should be `observer.observe(element`. –  Jun 02 '15 at 18:26
  • And it is `subtree` not `subTree`. Now it works. Sorry. –  Jun 02 '15 at 20:22
  • No errors now, but when I press gimme! I don't get the new elements... Could you check the pen again? – Vandervals Jun 05 '15 at 11:35
  • 2
    Oh my. It really looks like I have to test my code better. See fixes. –  Jun 05 '15 at 12:53
  • I don't understand how this notifies you when a new element has been added to the array, you would have to check it on a timer or something. I think this could work better with a callback that is called when items are added to the array. – Dustin Poissant Mar 25 '19 at 18:09
1

I don't think it is possible because subsequent changes of the DOM does not reflect in the NodeList object returned by the querySelectorAll() method.

Selectors-api W3C

angellica.araujo
  • 298
  • 1
  • 12