Why doesn't document.addEventListener('load', function) work in a greasemonkey script?
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);
Solution 1:
Apparently, document.addEventListener()
is unreliable, and hence, my error. Use window.addEventListener()
with the same parameters, instead.
Solution 2:
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 alert
ing 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)
Solution 3:
To get the value of my drop down box on page load, I use
document.addEventListener('DOMContentLoaded',fnName);
Hope this helps some one.
Solution 4:
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?