The problem I'm trying to solve is an ad loading script, that loads the ad code with jsonp and inserts it into the dom.
Now sometimes the ad code will include javascript tags, and i figured it was just a matter of moving them to the head section and they would run. In theory that works fine but when i made a script to move script tags to the head i ran into some weird behavior.
So I wrote this code to test just the script moving part, eliminating the rest of the code as an error source.
I get the same results, if I have just two scripts in the div it moves one of them, if I have 3 scripts it moves 2 of them. In the code pasted below it moves script 1 and 3, skipping the remote javascript reference and the last script-tag.
Would be interesting to at least know why this happens, and if it can be solved.
Edit: To clarify one thing, if i put the remote jquery script first and one of the simple script tags second it will move the remote script tag to the head fine and skip the second script tag.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
// get div id
function test() {
var td = document.getElementById('testId');
var scripts = td.getElementsByTagName("script");
console.log("No. of scripts to transfer to head: "+scripts.length);
for(i=0;i<scripts.length;i++) {
var curScript = scripts[i];
document.head.appendChild(curScript);
}
}
</script>
</head>
<body onload="test();">
<div id="testId">
<script type="text/javascript">var firstScript = 1;</script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">var secondScript = 1;</script>
<script type="text/javascript">var thirdScript = 1;</script>
</div>
</body>
</html>
You're laboring under a false assumption: It doesn't matter whatsoever whether
script
elements are in thehead
orbody
, they get run regardless. Moving them after they've been appended to the DOM is at best pointless, and at worst may cause unfortunate side-effects if the script is re-run when moved (but I don't think it is).As for why you're seeing the behavior you're seeing, it's because
getElementsByTagName
returns a liveNodeList
. When you move a script, it gets removed from theNodeList
. So given your four scripts, you'll get back aNodeList
initially containing four elements, so.length
is4
and[0]
is your first script. When you move that script out of thediv
, theNodeList
is updated because the script is no longer in thediv
, so its length is now3
and[0]
refers to your second script (the one loading jQuery).You can avoid having this behavior interrupt your loop in two ways:
Loop backward, from
.length - 1
to0
inclusive, orTurn the
NodeList
into an array, so the elements aren't moved out from under you.