Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DOMContentLoaded only once

I'm using this code for firefox extension

1: var Test {
2:  f: function() {
3:    alert("DOM content loaded");
4:    window.removeEventListener("DOMContentLoaded", function(e) { Test.f(); }, false);
5:  }
6: }
7: window.addEventListener("DOMContentLoaded", function(e) { Test.f(); }, false);

It should execute the code in function f() when DOM content (weg page) was loaded, it means it should give me one alert if I open new page or new tab or reload a page. The problem is, it gives me about 20 alerts, instead of one.
The problem is even worse if I want in function f() append to every anchor some text (e.g. if I want to append the text "(com)" it will append "(com)(com)(com)(com)(com)"

Do you know how to achieve the behaviour I want? removeEventListener didn't help.

The culprit seems to be other firefox extensions and about:blank. Is it possible that my event listener on DOMContentLoaded ignores page loads causes by other extensions?

thank you

like image 752
xralf Avatar asked Jun 07 '11 07:06

xralf


2 Answers

DOMContentLoaded generally only fires once per document so I suspect that you are catching events from the page's frames as well. Impossible to tell for sure with the information provided.

I can tell why you fail to remove the listener however. function(e) { Test.f(); } is a closure, each time this code runs a new function is created. So the function you add as a listener is different from the function you remove. Try the following for example:

alert(function(e) { Test.f(); } == function(e) { Test.f(); });

To avoid this problem you need to actually remember your closure, e.g.:

var listener = function(e)
{
    window.removeEventListener("DOMContentLoaded", listener, false);
    Test.f();
}
window.addEventListener("DOMContentLoaded", listener, false);
like image 76
Wladimir Palant Avatar answered Nov 13 '22 09:11

Wladimir Palant


You need to test whether or not DOMContentLoaded is being triggered by a frame load or the main document load, and only execute your function in the latter case:

    var Test {
        f: function() {
            if (!event.originalTarget.defaultView.frameElement) {
                alert("DOM content loaded");
            }
        }
    }

    window.addEventListener("DOMContentLoaded", function(e) { Test.f(); }, false);
like image 40
Amir Nathoo Avatar answered Nov 13 '22 11:11

Amir Nathoo