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, .....
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;
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…