Is it safe to assume that the last script
element* in the document when the script runs** is the currently running script?
For example, I want to create a script that can be dropped anywhere in the body of of a page and display an element in the same place. I'm doing something like this:
function getCurrentScriptElement() {
var scripts = document.getElementsByTagName('script');
return scripts[scripts.length - 1];
}
var script = getCurrentScriptElement();
var view = document.createElement('span');
/* Put stuff in our view... */
script.parentNode.insertBefore(view, script);
Assuming the script is in the body of the document, is this "safe?" Will the getCurrentScriptElement
function always return the running script? If not, how can it be done?
I'd like to do this without tying the script to a specific id attribute or similar, I'd like it to just be positional.
I created an example here that pulls in this script. One answer suggested that other scripts could create a condition where an example like this would break. Is it possible to add other scripts to this example that will break it?
It was suggested that other scripts with defer
or async
attributes could break this. Can anyone give an example of how such a script might work?
As I understand it, defer
means load the DOM first, and then run the script with the defer
tag. How would the defer
attribute appearing on another script element affect the behavior of getCurrentScriptElement
?
async
, as I understand it, means start fetching that script and keep parsing the DOM at the same time, don't wait... but when it hits my script it should still stop and wait, right?
I don't see how either one could affect it, can anyone provide an example?
* I'm only interested in external scripts for the purpose of this question.
** Not the last script
element in the entire document, but the last script
element in the document at the time when it runs. The rest of the document shouldn't be loaded yet, right?
Script tags are executed in the order they appear It also means scripts which appear later on the page can depend on things scripts which appear earlier have done. Elements on the page won't render until all the script tags preceding them have loaded and executed.
The <script> HTML element is used to embed executable code or data; this is typically used to embed or refer to JavaScript code. The <script> element can also be used with other languages, such as WebGL's GLSL shader programming language and JSON.
Use document. document. currentScript will return the <script> element whose script is currently being processed.
Why <script> tags should be placed at the end of body tag? As we know that HTML is loaded and executed line by line. So, when the browser encounters a <script> tag, it loads and executes the javascript code on the spot.
It's not an absolute guarantee no. Check out this JSFiddle: http://jsfiddle.net/jAsek/
<!DOCTYPE html>
<title>Test case</title>
<div>
<p>At the start</p>
<script id="first">
var scr1 = document.createElement("script");
scr1.setAttribute("id", "early");
document.body.appendChild(scr1);
</script>
<p>After the first script</p>
<script id="second">
function getCurrentScriptElement() {
var scripts = document.getElementsByTagName('script');
return scripts[scripts.length - 1];
}
alert(getCurrentScriptElement().id);
</script>
<p>At the end</p>
</div>
Here the alert reports the id of the injected script "early", not the id of currently running script "second".
There's no practical difference between internal and external scripts.
I don’t think it’s a safe assumption at all, as browsers execute javascript code quite differently depending on a number of things (like if you have other script elements in the head, if they are external etc.).
You should just require people to use a dummy element with a custom id or class. That way you will also make it possible to do whatever you do multiple times a page without having to run the script multiple times.
This is also what is done when using widgets, for example Google’s +1 button.
An alternative would be to use document.write
to write additional content while the script is executed. This will not replace the script tag however, but simply add something after it.
You probably want to use document.currentScript that is currently supported by 90% of browsers and fallback to document.scripts[document.scripts.length-1] if you're targetting IE
function writeHere(element)
{
var sc = document.currentScript || document.scripts[document.scripts.length-1] ;
sc.parentNode.insertBefore(element, sc);
// or in jquery $(sc).before($(element));
}
note: I didn't test document.scripts[document.scripts.length-1]
thoroughly but it should work in most cases (but not in Alohci exemple).
And this is a fix for IE so who cares :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With