Javascripts added via appendChild don't seem to run - javascript

I've got a javascript file being added dynamically to a page. If I use document.write, it works fine:
<html>
<head></head>
<body>
<script type="text/javascript">
var src = 'myDynamicScript.js';
document.write('<scr' + 'ipt type="text/javascript" src="' + src + '"></scr' + 'ipt>');
</script>
</body>
</html>
However, if I use appendChild, as outlined in this answer, the script gets downloaded, but never runs:
<html>
<head></head>
<body>
<script type="text/javascript">
var src = 'myDynamicScript.js';
var script = document.createElement("script");
script.type = "text/javascript";
script.src = src;
document.body.appendChild(script);
</script>
</body>
</html>
I've got a simple example set-up here (write) and here (append). Should I expect it to run, or is that the known behavior? If it should, why isn't it?

Your script is running all right, you just can't document.write from it. Use an alert or something to test it and avoid using document.write altogether.

Your examples work for me in Safari. Here are some questions:
What browsers are you testing? (Guessing you're having trouble on IE.)
Are you trying this from a server and not just dragging index.html into your browser?
What else is running on the page that might be blocking myDynamicServer.js?
Has something hijacked window.onload?
Have you tried appending myDynamicServer.js to document.getElementsByTagName('BODY')[0] and not document.body?

Related

Loading external script after a page has loaded

If I include this script tag in the header or the body of an HTML document, then the external script it points to will be executed:
<script type="text/javascript" src="http://www.example.com/script.js"></script>
If I add that same script tag to the page AFTER it has finished loading, either by using another script in the page or by running a javascript: URI, the external script will not load.
This is an HTML document that tries to do what I'm talking about:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
function f () {
var s;
s = document.createElement("script");
s.setAttribute("type", "text/javascript");
s.setAttribute("src", "https://code.jquery.com/jquery-3.4.1.min.js");
document.body.appendChild(s);
alert(typeof $);
}
</script>
</head>
<body onload="f();">
</body>
</html>
If you open this document in a web browser, the JavaScript pop-up dialogue will say "undefined" instead of "object". If it said "object", then that would mean that the jQuery code had been loaded.
Another case would be a bookmarklet that requires JavaScript code that is not used by the page it is run on. For example, if a bookmarklet needs jQuery and the page that it is run on does not use jQuery, it might do this:
s = document.createElement("script");
s.setAttribute("type", "text/javascript");
s.setAttribute("src", "https://code.jquery.com/jquery-3.4.1.min.js");
document.body.appendChild(s);
The above code does not result in jQuery being loaded.
What can I do to load a script after an HTML page has loaded? I do not want to use any JavaScript libraries because that would require the library code to have already been loaded by the page.
Appending scripts with javascript loads them asynchronously. Add an onload handler to execute what code you want
<script type="text/javascript">
function f () {
var s;
s = document.createElement("script");
s.setAttribute("type", "text/javascript");
s.setAttribute("src", "https://code.jquery.com/jquery-3.4.1.min.js");
document.body.appendChild(s);
s.onload=function(){alert(typeof $)};
}
</script>
What can I do to load a script after an HTML page has loaded?
Put
<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js">
after the closing of the body. An html page is rendered from top to bottom so only when the body has been loaded the browser will download the script (if not already in cache). In this way you can put another script after this to console log typedef if your really need it

Inject external javascript file out of time

I want to load an external javascript. This javascript contains source for an ad. I use a method of injection because the javascript needs the user IP. The javascript code to use is:
<html>
<head>
<script type="text/javascript">var userip;</script>
<script type="text/javascript" src="http://service.get.userip?var=userip"></script>
<script>
var url="http://example.com/abc?user_ip=" + userip;
var headID = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.src = url;
headID.appendChild(newScript);
</script>
</head>
</html>
I use a service javascript to get the IP of user ("http://service.get.userip?var=userip" in this example code). Then I added the user IP to the url where I download the javascript.
The javascript is inserted when it revised the web charged with developer mode browser but it doesn't work.
I think the problem is that the JavaScrip injection is slow and this is no time to charge properly.
In my tests I got a proper operation to put a alert before the end of the last script:
<script>
...
headID.appendChild(newScript);
alert("Script is Load!");
</script>
For this reason I think the problem is load time. I also try loops, sleep() and setTimeout(), but I do not reproduce the smooth running that I get with the alert().

How can I include a script with document.write?

We need to add a script to our web application. It basically adds an corporate menu.
So we've received a script to include in the body of our web application:
<!-- BEGIN NAVIGATION -->
<script type="text/javascript" src="https://intranet.local/?getCorporateJsMenu"></script>
<!-- END NAVIGATION -->
And the content of https://intranet.local/?getCorporateJsMenu basically looks like this:
document.write('<script type="text/javascript" src="..."></script>');
//....
document.write('<div>');
document.write('<ul>');
//...
document.write('<li>...</li>');
//...
document.write('</ul>');
document.write('</div>');
After having placed the <!--NAVIGATION--><script... directly into the HTML body, we were experiencing severe page load performance problems.
So our idea was to add the menu with JavaScript, when everything has already been loaded with something like this:
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://intranet.local/?getCorporateJsMenu';
var domparent = jQuery('#header').get();
domparent[0].appendChild(script);
With Firebug we see, that the script element has been added to the HTML content and the script has been loaded from the network, but somehow the document.write of the loaded script doesn't get executed. Why?
We cannot modify the contents of https://intranet.local/?getCorporateJsMenu since it comes from third party.
This happens because the script execution stops at the first found literal </script> tag, no matter if it was enclosed in the parenthesis. You need to obfuscate the ending script tag, for example:
document.write('<script type="text/javascript" src="..."><\/script>');
However, it seems you use also jQuery. Why not use the jQuery methods to load a script and add the content to a page rather than document.write()?
Here is an example of hijacking document.write() to bring 21st century loading performance to legacy scripts:
<script>
var writes = [];
document.write = [].push.bind(writes);
</script>
<div id=targ></div>
<script type="text/javascript" src="https://intranet.local/?getCorporateJsMenu"></script>
<script>
document.getElementById("targ").innerHTML = writes.join(" ");
</script>
I've used the patterns to support ads on a SPA site, as well as to cache embeds, and in one case to modify the content's style before injecting.
Try this:
document.write('<scr' + 'ipt type="text/javascript" src="..."></scr' + 'ipt>');

Insert code snippet to div

I used Jquery to insert a variable to div. Please check my code.
var msg = '<script src="https://gist.github.com/3010234.js?file=new.html.erb"></script>'
$('.result').html(msg);
msg variable contains a script that render a code snippet. msg is dynamic variable.
The above code is not working to insert code snippet to div.
Any Idea?
This script generate code snippet like this.
To add script, I would add it to head like this;
var s = document.createElement('script');
s.src = 'https://gist.github.com/3010234.js?file=new.html.erb';
s.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(s);
You cannot load a github gist into a page dynamically using that embed code. The embed code is fine if you can add the script tag to the HTML, but to do it dynamically via JavaScript as you are trying to do, it won't work because it relies on document.write().
Instead, use the github gists api:
$.get("https://api.github.com/gists/3010234", function(response) {
$(".result").text(response.data.files["new.html.erb"].content);
}, "jsonp");
Working demo: http://jsfiddle.net/naTqe/
function loadScript() {
var script = document.createElement("script");
script.src = "https://gist.github.com/3010234.js?file=new.html.erb";
script.type = "text/javascript";
document.getElementById("result").appendChild(script);
}
It looks like your remote JS is buggy. I ran it through JS Lint and came up with several errors.
Anyway, here is my working example. Keep a javascript console open and you'll see the error when it tries to parse the remote JS.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src=
"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<title>Jquery test</title>
</head>
<body>
<h1>jQuery</h1>
<p class="result">Some result</p>
<script>
/*<![CDATA[*/
$(document).ready(function(){
var msg = '<script type="text/javascript" src="http://gist.github.com/3010234.js?file=new.html.erb"><\/script>";
$('.result').html(msg);
});
/*]]>*/
</script>
</body>
</html>

Browser event when all JS files loaded

My AJAX app is basically one index.html plus a bunch of .js modules. My setup function hooks up the js handler code to the appropriate DOM element. I suspect I need to use window.onload() rather than jquery's $(document).ready() since all the .js files need to be available (i.e. downloaded) at hookup time.
My understanding is that only the DOM tree is ready at $(document).ready(), but there's no guarantee that the .js files have been loaded. Is that correct?
PS. I don't need multiple onload handlers; a single window.onload() is fine for me.
You definitely have a misunderstanding in this case. The whole reason why it is considered best practice to include your script tags just before the close of the body tag is because script loads are blocking loads. Unless specifically coded otherwise (i.e.; google analytics), JavaScript files are loaded synchronously.
That said, if there are dependencies between script files, the order in which the files are loaded can be important.
No, you can safely use $(document).ready() as long as your script tags are loaded synchronously (in most cases, this means "normally"). The browser waits for a <script> to be loaded before continuing. Therefore, $(document).ready() includes all <script> tags in the source.
There are two exceptions to this, if the script tags contains an async or defer attribute. The prior meaning the compatible browsers can continue rendering the page, and the latter signifying that the script is executed when the page has finished.
I setup two files as a test:
syncscript.html
<html>
<head>
<title></title>
<style type="text/css">
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(window).load(function(){
$(document.body).append('<p>window.load has run.');
});
$(document).ready(function(){
$(document.body).append('<p>document.ready has run.');
});
</script>
</head>
<body>
<p>Page has loaded. Now continuing page load and attempting to load additional script file (after 10 second pause).</p>
<script type="text/javascript">
var p = document.createElement('p');
p.innerHTML = '<p>Inline script preceding jssleep.php file has run.</p>';
document.body.appendChild(p);
</script>
<script type="text/javascript" src="http://jfcoder.com/test/jssleep.php"></script>
<script type="text/javascript">
var p = document.createElement('p');
p.innerHTML = '<p>This is an inline script that runs after the jssleep.php script file has loaded/run.</p>';
document.body.appendChild(p);
</script>
</body>
</html>
jssleep.php
<?php
header("content-type: text/javascript");
sleep(10);
?>
var p = document.createElement('p');
p.innerHTML = '<p>jssleep.php script file has loaded and run following <?php sleep(10); ?>.</p>';
document.body.appendChild(p);
This outputs (in Firefox):
Page has begun loading. Now continuing page load and attempting to
load additional script file (after 10 second pause).
Inline script preceding jssleep.php file has run.
jssleep.php script file has loaded and run following <?php sleep(10);
?>.
This is an inline script that runs after the jssleep.php script file
has loaded/run.
$(document).ready() has run.
$(window).load() has run.
That is correct. However window.onload also requires CSS and images to be downloaded, so may be a bit overkill.
What you can do is this:
var scriptsToLoad = 0;
// for each script:
s = document.createElement('script');
s.type = "text/javascript";
s.src = "path/to/file.js";
scriptsToLoad += 1;
s.onload = function() {scriptsToLoad -= 1;};
// after all scripts are added in the code:
var timer = setInterval(function() {
if( scriptsToLoad == 0) {
clearInterval(timer);
// do stuff here
}
},25);

Categories

Resources