0

I'm developing a chrome plugin that inject a class to every element in the page. But in pages such as facebook or twitter there is content loaded dynamically, so I use this code to check when this conent is loaded:

document.addEventListener('DOMNodeInserted', function() {
    console.log('fatto');
}, true);

the problem is that this way, the script is fired every single time a node is inserted. Therefore I'd like to add some kind of limitation. something like: When a node is inserted fire the script and then wait 2 sec.

I'm trying something like this but no success:

var check = 1;

document.addEventListener('DOMNodeInserted', function() {
    if(check == 1) {
        check = 0;
        setInterval( function() {

            //do stuff

            check = 1;

        }, 1000);

        console.log('fatto');
    }
}, true);

thanks

000
  • 26,951
  • 10
  • 71
  • 101
slwr
  • 1,105
  • 6
  • 16
  • 35

2 Answers2

1

I've seen this technique referred to as debouncing. Here's an example:

(function() {
    var timer;

    var doStuff = function() {
        timer = null;
        alert("Doing stuff");
    };

    document.addEventListener('DOMNodeInserted', function() {
        if (timer) {
            window.clearTimeout(timer);
        }
        timer = window.setTimeout(doStuff, 2000);
    }, false);
})();

You can generalize this:

function addDebouncedEventListener(obj, eventType, listener, delay) {
    var timer;

    obj.addEventListener(eventType, function(evt) {
        if (timer) {
            window.clearTimeout(timer);
        }
        timer = window.setTimeout(function() {
            timer = null;
            listener.call(obj, evt);
        }, delay);
    }, false);
}

addDebouncedEventListener(document, 'DOMNodeInserted', function(evt) {
    alert(evt.target.nodeName + " inserted");
}, 2000);
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • If I understand your code correctly this may theoretically delay execution of the `doStuff` function indefinitely (ie. when `DOMNodeInserted` event is called every second). – Konrad Dzwinel Jun 06 '12 at 11:20
  • @kdzwinel: Yes. I'm not sure from the question whether that's what the requirement is. – Tim Down Jun 06 '12 at 11:21
  • OP may end up with nasty delay in `doStuff()` execution when the page like Facebook/Twitter is loading. A lot of elements are inserted there when the page is first opened. But that's just an assumption, it needs to be tested. Very nice code BTW! – Konrad Dzwinel Jun 06 '12 at 11:32
0

I'd say:

var timeout;

document.addEventListener('DOMNodeInserted', function() {
    startNewTimeout();
}, true);

function startNewTimeout() {
    //only if there is no active timeout already
    if(timeout === undefined) {
        timeout = setTimeout( function() {

           timeout = undefined;
           //do stuff

        }, 1000);
    }
}

​This script won't delay the execution of //do stuff indefinitely. It will make sure that //do stuff is executed max. 1sec after first DOMNodeInserted event.

Konrad Dzwinel
  • 36,825
  • 12
  • 98
  • 105