I have a question about inserting a dynamically created script with JavaScript.
This is the code I'm using:
var body = document.getElementsByTagName('body')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'code.js';
body.appendChild(script);
I usually place scripts at the bottom of the page, but if it's dynamically inserted like this, is there a way to ensure that the script is placed at the bottom of the page?
If it's dynamically inserted like this, is there a way to ensure that the script is placed at the bottom of the page?
You already do that with body.appendChild(script); of course there might be other elements inserted after it later on.
However, as you are dynamically inserting the script, there is absolutely no need to ensure placing it at any certain location - it is loaded and executed asynchronously (neither blocking something nor waiting for something). You may place it anywhere in the document, and even remove it right away, it will not influence any load or execute behaviour.
There's a way to ensure that using Jquery. The code.js will be called after DOM is loaded and putted right before </body> tag:
$(function() {
var body = document.getElementsByTagName('body')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'code.js';
body.appendChild(script);
});
Related
I'm creating an iFrame dynamically and I've injected an external js library to it.
Everything is working fine. I have my iFrame builded containing the script tag with the library in the head tag of the library. Now I would like to execute a function that is written in that library. Here is the code that I use to add the script dynamically:
var head = parentFrameContentWindow.getElementsByTagName('head')[0];
var script = parentFrameContentWindow.createElement('script');
script.src = "http://localhost:8080/project/js/project-interactions.js";
script.type = 'text/javascript';
script.onload = function() {
}
head.appendChild(script)
I've added the onload attribut to the script tag but when I try to fire up a simple function that triggers an alert method contained but the external library, I get and undefined function error. Someone knows how to achieve that ?
I am dynamically adding <script> tags for different .js resources into the head, however I receive an error exclaiming that jQuery is not defined.
I know that jQuery is in fact working, as other functions further down the flow are working correctly. Below is the code that I am using to dynamically add these scripts to the header. As you can see, I also include jQuery before any other plugins.
document.addEventListener("DOMContentLoaded", AddExternals)
function AddExternals(){
var jq = document.createElement("script");
jq.type = "text/javascript";
jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js";
var t2e = document.createElement("script");
t2e.type = "text/javascript";
t2e.src = "/test/rfsystem/rfJavascript/table2excel.js";
document.getElementsByTagName("head")[0].appendChild(jq);
document.getElementsByTagName("head")[0].appendChild(t2e);
console.log(jQuery);
}
Just after appending the script tag you can not expect that the script has been pulled over from the network and is embedded on to your page. It will load asynchronously.
You need to wait, or you can use .onload on that script.
Ex:
You should also append the script to the DOM before attaching the onload event and You should set the src attribute after the onload event:
var jq = document.createElement("script");
jq.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(jq);
jq.onload = function() { console.log(jQuery); };
jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js";
I maintain some donation forms that include the GeoTrust SSL 'smart icon'. This is generated by including a script reference as so within the document where you want the seal to appear:
<script type="text/javascript" src="//smarticon.geotrust.com/si.js"></script>
Their script is obviously doing a document.write(), and if/when geotrust is being slow it blocks rendering of my donation form for up to a few seconds.
I can't use the 'async' attribute, because of the document.write(). I can't edit or rewrite GeoTrust's javascript of course. And loading the js in the footer or doing the 'append to the head' approach doesn't help either because the script needs to execute within the markup where we want the icon to appear. A further complication is that these donate pages are also part of a different third-party system full of their own javascript etc.
Here's an approach that seems to work, but I'm wondering if there's a better way:
<div id="vs_seal"></div>
<script type="text/javascript">
r(function() {
var div = document.getElementById('vs_seal');
writebackup = document.write;
document.write = function(markup) {
div.innerHTML = markup;
document.write = writebackup;
}
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= '//smarticon.geotrust.com/si.js';
document.body.appendChild(script);
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
</script>
(PS I totally stole that domready test from http://www.dustindiaz.com/smallest-domready-ever )
EDIT: If it isn't clear, what I'm doing is
writing a div
waiting for the dom to be ready (last line)
saving document.write as a variable
overriding document.write to instead insert the output into a div
loading the script dynamically via appendChild
when the script calls the overriden document.write, the last line of the override is to reset document.write to the original version (that I saved as a variable).
EDIT: After the comments below, I've simply put it into an IFRAME instead.
<style>#vs_seal iframe{border:0 none;}</style>
<div id="vs_seal"></div>
<script type="text/javascript">
r(function() {
var div = document.getElementById('vs_seal');
var iframe = document.createElement('iframe');
iframe.width = 118;
iframe.height = 55;
iframe.frameborder = 0;
iframe.scrolling = "no";
iframe.seamless = "true";
iframe.src = 'about:blank';
var content = '<!DOCTYPE html>'
+ '<head><title>Dynamic iframe</title>'
+ '<style>body{margin:0;padding:0;border:0;}</style></head>'
+ '<body><script type="text/javascript" src="//smarticon.geotrust.com/si.js">'
+ '<\/script><\/body><\/html>';
div.appendChild(iframe);
iframe.contentWindow.document.open('text/html', 'replace');
iframe.contentWindow.document.write(content);
iframe.contentWindow.document.close();
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
</script>
I originally tried pulling in the content into a hidden IFRAME and then copying the innerHTML from the IFRAME into my div, but GeoTrust's javascript that makes their popup window all pretty needs to be executed in the context its being clicked on. The innerHTML doesn't execute the javascript, and there seemed to be no advantage to not just displaying the IFRAME.
Thanks for the comments and suggestions!
I have a pixel script I want to insert only on a certain page. Because of our awful CMS, I can't add it to the page itself, but I can add it to the master template ASP (I think it's ASP) file. I figured it would be easiest to do this in Javascript.
Right now I have this in the head, but I don't think printing the pixel script in the head will work:
<script>
if (location.href.indexOf("http://site.com/page1") !== -1) {
document.write('<script src="yadayada" type="text/javascript"></script>');
}
</script>
<script>
if (location.href.indexOf("http://site.com/page1") !== -1) {
var script = document.createElement("script");
script.src="yadayada.js";
script.type="text/javascript";
script.onload=function(){
// callback after script loading is complete
// your script dependent code goes here
}
document.body.appendChild(script)
}
</script>
This is how it can be done
Obviously, it would be better to do this on backend, but if you really can not, here is what is wrong with your code:
The </script> part of the string you are trying to append to the document is actually closing your script tag in the head.
This is a common approach to avoid this problem:
document.write('<script src="yadayada" type="text/javascript"></' + 'script>');
Other solution would be to create the script element using document.createElement:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "example.com/somescript.js";
document.body.appendChild(script);
I'm dynamically inserting a <script> tag with a src attribute and no content. But the browser does not pull down that src and run the script after the insertion -- the tag just sits there in the DOM.
Is it possible for me to tell the browser to "run" the script tag?
Because of the other code I'm working with, it's easier for me to keep the code fetched via the src attribute than to fetch it myself and insert it into the body of the tag -- but if that's necessary, I can do that too (and welcome any advice on that).
update with requested info
The script tag is inserted based on user interaction an arbitrary number of times after the page has loaded
I'm inserted the tag like this (jquery's html function strips out script tags): document.getElementById("my-div").innerHTML = "the script tag, which stack overflow wants to strip";
Try following code:: Its working
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src =MY_URL;
$("#YOUR_ELEMNT_ID").append( script );
it should run right after the browser inserts the script into the dom, but you can try to wrap your script into a function and call that function after the script loads :
var script = document.createElement('script');
script.setAttribute('type','text/javascript');
script.setAttribute('src',script_url);
script.onreadystatechange= function () {
if (this.readyState == 'complete')
initScript();//the whole script is wrapped in this function
}
script.onload= initScript;
Hope this helps!
You could have a setTimeout in the main script to check if the new script is there.. and if it is, then run it. Do you know if it downloads the file or if it just does nothing? Check with Chrome's Network monitor.
I think there's a dynamic way to load Javascript without the src= tag, as well, but I haven't personally done it.
Why not have all the javascript pre-loaded and just put through some inline JS to execute it?