62

It doesn't give an error, and I put a console.log('loaded userscript wifi-autologin'), the console.log works, but the intended effect of the document.addEventListener doesn't happen. After doing a bit more debugging, making it print that the addEventListener was called, I discovered that it wasn't being called.

Source of script:

// ==UserScript==
// @name        wifi-autologin
// @namespace   lf-ns
// @description Hopefully autologins to a captive portal
// @include     *://1.1.1.1/*
// @version     1
// @run-at document-end
// ==/UserScript==

document.addEventListener('load', submitAction);
kenorb
  • 118,428
  • 63
  • 588
  • 624
Yet Another User
  • 2,081
  • 2
  • 14
  • 27
  • 10
    Listen for the load event on `window`. – Paul S. May 06 '13 at 17:57
  • 1
    You mean `window.addEventListener()`? – Yet Another User May 06 '13 at 17:58
  • Yep, although both work ( see http://jsbin.com/aqoweb/1 ), I find using `window` is much more reliable. – Paul S. May 06 '13 at 18:13
  • 1
    @PaulS. From what I can see in the pastebin you linked, all `addEventListener`s are being appended to `window` (even the one which is meant to be hooked to document as the comment in the code and the message in the console says). There's no `document.addEventListener('load' ...` in the source code :-/ – david.binda Sep 27 '15 at 18:12
  • I agree @david.binda, the example of Paul S. does not test document event handlers. just window ones. – Alex MM Oct 22 '15 at 13:17

5 Answers5

106

Apparently, document.addEventListener() is unreliable, and hence, my error. Use window.addEventListener() with the same parameters, instead.

Yet Another User
  • 2,081
  • 2
  • 14
  • 27
  • 9
    How did you get to the conclusion of that `document.addEventListener('load',...)` is unreliable? – Alex MM Oct 23 '15 at 07:53
  • @AlexMM 1. See comment on first answer. 2. This one actually works properly. – Yet Another User Oct 23 '15 at 13:26
  • 2
    I had already seen the comment saying _"Listen for the load event on window"_ and the [jsfiddle](http://jsfiddle.net/AlexMM/7uz4rjkc/) I did confirms it works. But the thing is, why is it not working on `document`? According to the documentation I wrote on my response it should work. So what I wanted to know is if you understood why it is not working on `document`. – Alex MM Oct 24 '15 at 16:29
  • @AlexMM I have no idea. I have decided that it's just gremlins. – Yet Another User Oct 24 '15 at 16:30
  • Bad news then. The funny thing is that the event `DOMContentLoaded` does fire on `document`, and it is an event previous to `load` event so it is weird why one is fired and the other not. – Alex MM Oct 24 '15 at 16:34
  • in chrome, I'm getting document 'load' event to fire if i set the `useCapture` option to `true`. However, it's firing twice; more gremlins? – Barrard Jan 26 '17 at 04:03
7

The problem is WHEN the event is added and EXECUTED via triggering (the document onload property modification can be verified by examining the properties list).

When does this execute and modify onload relative to the onload event trigger:

document.addEventListener('load', ... );

before, during or after the load and/or render of the page's HTML?
This simple scURIple (cut & paste to URL) "works" w/o alerting as naively expected:

data:text/html;charset=utf-8,
    <html content editable><head>
          <script>
                document.addEventListener('load', function(){ alert(42) } );
          </script>
          </head><body>goodbye universe - hello muiltiverse</body>
    </html>

Does loading imply script contents have been executed?

A little out of this world expansion ...
Consider a slight modification:

data:text/html;charset=utf-8,
    <html content editable><head>
          <script>
              if(confirm("expand mind?"))document.addEventListener('load', function(){ alert(42) } );
          </script>
        </head><body>goodbye universe - hello muiltiverse</body>
    </html>

and whether the HTML has been loaded or not.

Rendering is certainly pending since goodbye universe - hello muiltiverse is not seen on screen but, does not the confirm( ... ) have to be already loaded to be executed? ... and so document.addEventListener('load', ... ) ... ?

In other words, can you execute code to check for self-loading when the code itself is not yet loaded?

Or, another way of looking at the situation, if the code is executable and executed then it has ALREADY been loaded as a done deal and to retroactively check when the transition occurred between not yet loaded and loaded is a priori fait accompli.

So which comes first: loading and executing the code or using the code's functionality though not loaded?

onload as a window property works because it is subordinate to the object and not self-referential as in the document case, ie. it's the window's contents, via document, that determine the loaded question err situation.

PS.: When do the following fail to alert(...)? (personally experienced gotcha's):

caveat: unless loading to the same window is really fast ... clobbering is the order of the day
so what is really needed below when using the same named window:

window.open(URIstr1,"w") .
   addEventListener('load', 
      function(){ alert(42); 
         window.open(URIstr2,"w") .
            addEventListener('load', 
               function(){ alert(43); 
                  window.open(URIstr3,"w") .
                     addEventListener('load', 
                        function(){ alert(44); 
                 /*  ...  */
                        } )
               } )
      } ) 

alternatively, proceed each successive window.open with:
alert("press Ok either after # alert shows pending load is done or inspired via divine intervention" );

data:text/html;charset=utf-8,
    <html content editable><head><!-- tagging fluff --><script>

        window.open(
            "data:text/plain, has no DOM or" ,"Window"
         ) . addEventListener('load', function(){ alert(42) } )

        window.open(
            "data:text/plain, has no DOM but" ,"Window"
         ) . addEventListener('load', function(){ alert(4) } )

        window.open(
            "data:text/html,<html><body>has DOM and", "Window"
         ) . addEventListener('load', function(){ alert(2) } )

        window.open(
            "data:text/html,<html><body>has DOM and", "noWindow"
         ) . addEventListener('load', function(){ alert(1) } )

        /* etc. including where body has onload=... in each appropriate open */

    </script><!-- terminating fluff --></head></html>

which emphasize onload differences as a document or window property.

Another caveat concerns preserving XSS, Cross Site Scripting, and SOP, Same Origin Policy rules which may allow loading an HTML URI but not modifying it's content to check for same. If a scURIple is run as a bookmarklet/scriplet from the same origin/site then there maybe success.

ie. From an arbitrary page, this link will do the load but not likely do alert('done'):

    <a href="javascript:window.open('view-source:http://google.ca') . 
                   addEventListener( 'load',  function(){ alert('done') }  )"> src. vu </a>

but if the link is bookmarked and then clicked when viewing a google.ca page, it does both.

test environment:

 window.navigator.userAgent = 
   Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4 (Splashtop-v1.2.17.0)
ekim
  • 87
  • 1
  • 2
5

To get the value of my drop down box on page load, I use

document.addEventListener('DOMContentLoaded',fnName);

Hope this helps some one.

Bruce Tong
  • 1,020
  • 11
  • 12
1

According to HTML living standard specification, the load event is

Fired at the Window when the document has finished loading; fired at an element containing a resource (e.g. img, embed) when its resource has finished loading

I.e. load event is not fired on document object.

Credit: Why does document.addEventListener(‘load’, handler) not work?

czerny
  • 11,433
  • 12
  • 57
  • 80
0

this happened again around last quarter of 2017 . greasemonkey firing too late . after domcontentloaded event already been fired.

what to do:

  • i used @run-at document-start instead of document-end
  • updated firefox to 57.

from : https://github.com/greasemonkey/greasemonkey/issues/2769

Even as a (private) script writer I'm confused why my script isn't working.

The most likely problem is that the 'DOMContentLoaded' event is fired before the script is run. Now before you come back and say @run-at document-start is set, that directive isn't fully supported at the moment. Due to the very asynchronous nature of WebExtensions there's little guarantee on when something will be executed. When FF59 rolls around we'll have #2663 which will help. It'll actually help a lot of things, debugging too.

Community
  • 1
  • 1
bh_earth0
  • 1,902
  • 19
  • 21