0

I have a problem ..

The "DOMNodeInserted" is not working as it supposed to. I am not sure if I am using it properly.

Any ideas ?

Michael
  • 796
  • 11
  • 27

1 Answers1

4

EDIT: Scroll further down for an better approach using a MutationObserver.


When constructing the DOM at page-loading, no DOMNodeInserted events are fired. I don't think there is a way to have the HTML pass through your filter before being rendered (or if there is I don't know it).

Filtering on DOMContentLoaded instead, might be quick enough for the user not to notice the difference (or at least not to bother too much).

Of course, you have to listen for dynamic changes in the DOM (e.g. content loaded via AJAX etc) and filter it dynamicaly. A MutationObserver might come in handy for that.

Take a look at this demo code, to get you started on this approach:

manifest.json
(Note that for this to work you don't need any of the following:
browser_action, page_action, background, permissions)

...
"content_scripts": [
    {
        "matches": [
            "http://stackoverflow.com/*",
            "http://www.stackoverflow.com/*"
        ],
        "js":         ["content.js"],
        "run_at":     "document_start",
        "all_frames": true
    }
],
...

content.js

// Implement your filtering mechanism
// Good luck trying not to break the HTML :)
var doFilter = function(elem) {
    // Demo filtering: highlighting links 
    // (and possibly breaking HTML in many pages)
    elem.innerHTML = elem.innerHTML.replace(
        /(<a[^>]*)(>[^<]*<\/a>)/ig,
        "$1 style=\"background-color: yellow;\"$2");
};

window.addEventListener("DOMContentLoaded", function() {
    doFilter(document.body);
});

UPDATE

Here is a different approach using a MutationObserver, which is even more quick. Using this approach the changes should be virtualy "transparent" to the user.
(This still needs twicking, e.g. to handle dynamic node updates.)

content.js

// Highligth the element by giving it a yellow background
var doFilter = function(link) {
    link.style.backgroundColor = "yellow";
}

// Create a MutationObserver to handle events (i.e. filtering <a> elements)
var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        if (mutation.addedNodes) {
            for (var i = 0; i < mutation.addedNodes.length; i++) {
                var node = mutation.addedNodes[i];
                if (node.nodeName == "A") {
                    doFilter(node);
                }
            }
        }
    });
});

// Start observing "childList" events in document and its descendants
observer.observe(document, {
    childList:     true,
    subtree:       true
});

If you decide to go for the MutationObserver approach, there is this JS library that is supposed to make your life easier: mutation-summary

gkalpak
  • 47,844
  • 8
  • 105
  • 118
  • Wow you are awesome ! Thanks a lot for your comment. I will try your suggestinons asap. Do you have a good suggestion for dynamic DOM elements that are loaded at runtime ? – Michael Oct 26 '13 at 18:54
  • 1
    Without giving too much thought (or testing) to it, a MutationObserver to listen for `characterData` and `childList` changes in body and its descendants sounds like a reasonable place to start :) – gkalpak Oct 26 '13 at 23:06
  • Note: MutationObserver is only supported in IE versions 11+ – Alexey Mar 26 '14 at 10:53