Solution: There appears to have been an issue in the way I was calling my queuing mechanism into window.onload.
Preamble - I'm glad to see I'm being flagged as a duplicate, where the solution is to use window.onload, which is something I'm already using here. A couple comments have indicated possible issues with the queue that I got from another stackoverflow solution, but leave me in the dark due to lack of elaboration.
Question: If I make a function call in the head, it fails. If I make a function call in the body, it succeeds. Why?
Extension: Why do the calls to the same function in global.js, which is above the failing call, succeed?
I have some javascript that creates an onload "queue" of sorts (function addLoadEvent in global.js). A call to this function adds to the queue for when onload is called.
Except, I've found that a particular script function call fails if it's located in the head vs in the body. I can't figure out why, because everything that's needed (other js functions) are loaded above the function call itself, and the actual call to the function isn't triggered until onload, ensuring that the necessary html elements exist.
Order of loading:
- html file up to head
- global.js - including addLoadEvent(func)
- addLoadEvent x2 (succeeds)
- inline script in head - includes initialFighter()
- addLoadEvent (location one - fails)
- html file after head
- addLoadEvent (location two - succeeds)
- onload triggers queued calls
For the purpose of this question, the function call that fails or succeeds based on it's location is the following.
addLoadEvent(initialFighter());
Here's the stripped down HTML, note the 2 locations flagged. If I copy paste the above function call to Location one, it fails. If I copy paste the above function call to Location two, it succeeds.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="global.js"></script>
<script type="text/javascript">
function showFighter(id) {
var pic = document.getElementById("picture");
var picPath = 'url(images/' + id + '.png)';
pic.style.backgroundImage = (picPath);
}
function initialFighter() {
var fighter = getURLParameter('fighter');
if (typeof(fighter) != "undefined" && fighter != null) {
showFighter(fighter);
} else {
showFighter('Foobar');
}
}
***** LOCATION ONE *****
</script>
</head>
<body>
<header></header>
<nav id="nav"></nav>
<section id="fighters">
<div id="picture"></div>
<div id="text"></div>
<script type="text/javascript">
***** LOCATION TWO *****
</script>
</section>
<footer id="footer"></footer>
</body>
</html>
Below is global.js, which is the very first script file loaded:
Note that there are 2 addLoadEvent(func) calls here, and they succeed (don't run until after html elements exist) despite being above practically everything else.
function addLoadEvent(func) {
var prevOnLoad = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (prevOnLoad) {
prevOnLoad();
}
func();
}
}
}
function loadFile(id, filename) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById(id).innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open('GET', filename, true);
xmlhttp.send();
}
addLoadEvent(loadFile('nav', 'nav.txt'));
addLoadEvent(loadFile('footer', 'footer.txt'));
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}