Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
595 views
in Technique[技术] by (71.8m points)

javascript - chrome MutationObserver for new paragraph text

I haven't really understood quite yet how to use the mutationObserver but what I currently have seems somewhat right... I'd like to do an action every time new p tag appears within the code.. Here is my code thus far:

var target = $('p');
var observer = new WebKitMutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        chrome.storage.sync.get({ getInjection: true }, function(getInject) {
        var getInjectionState = getInject.getInjection;
        if(getInjectionState == true) {
                arrayOfP = $("p").text();
                chrome.runtime.sendMessage(arrayOfP, manageResponse);
            }
        });
    });    
});
observer.observe(target[0], { attributes: true, childList: true, characterData: true });

This code is within a content script in a chrome extension. Why isn't it working? Any help would be appreciated. Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  1. observer.observe should observe the parent/container element to which the new p elements are added or document.body.

    • observer.observe($('.some-container-selector')[0], .....
    • observer.observe(document.body, .....
  2. inside the callback you should check whether the added node is actually p:

    mutations.forEach(function(mutation) {
      Array.prototype.forEach.call(mutation.addedNodes, function(node) {
        if (node.nodeType != 1) return; // only process Node.ELEMENT_NODE
        if (node.localName != 'p') { // not P but might be DIV with P inside
          node = node.querySelector('p');
          if (!node) return;
        }
        // now we have our P node
        console.log("Got P!", node);
      });
    });
    


As an alternative here's a function I reuse for several years, with an uglier but much faster for-loop:

function setMutationHandler(baseNode, selector, cb) {
  new MutationObserver(function(mutations) {
    for (var i=0, ml=mutations.length, m; (i<ml) && (m=mutations[i]); i++)
      for (var j=0, nodes=m.addedNodes, nl=nodes.length, n; (j<nl) && (n=nodes[j]); j++)
        if (n.nodeType == 1) 
          if ((n = n.matches(selector) ? [n] : n.querySelectorAll(selector)) && n.length)
            if (!cb.call(this, [].slice.call(n)))
              return;
  }).observe(baseNode, {subtree:true, childList:true}); 
}

Usage (here the callback would receive only p elements under .some-container-class):

setMutationHandler(document, '.some-container-class p', function(nodes) {
  nodes.forEach(function(node) {
    console.log("Got node", node);
    // do something
  });
  //this.disconnect(); // disconnect the observer, useful for one-time jobs
  //return true; // continue enumerating current batch of mutations
});

The last for-loop occurs quite rarely comparing to the setMutationHandler's loops so it may be replaced with a more concise [].forEach.call(nodes, ... or Array.prototype.forEach.call(nodes, .... or jQuery wrapper with .each.

P.P.S. for Chrome pre-34 this is required somewhere at the start of the script:

if (!Element.prototype.matches)
    Element.prototype.matches = Element.prototype.webkitMatchesSelector;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...