Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it the last `script` element the currently running script?

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?

like image 856
Dagg Nabbit Avatar asked Jan 19 '13 00:01

Dagg Nabbit


People also ask

Are script tags executed in order?

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.

What is an script element?

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.

How may I reference the script tag that loaded the currently executing script?

Use document. document. currentScript will return the <script> element whose script is currently being processed.

Why script tag is at end of HTML?

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.


3 Answers

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.

like image 140
Alohci Avatar answered Oct 05 '22 18:10

Alohci


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.

like image 40
poke Avatar answered Oct 05 '22 19:10

poke


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 :)

like image 39
frenchone Avatar answered Oct 05 '22 20:10

frenchone