45

I want to add DOM element to head section of HTML. jQuery does not allow adding DOM element script to the head section and they execute instead, Reference.

I want to add script tags and write a script within <head> section.

var script = '<script type="text/javascript"> //function </script>'
$('head').append(script);

Something like this with functions. I tried jQuery and javascript\, but it does not work.

Please tell me how to add and write script to head by jQuery or javascript.

I tired the javascript to add DOM element, but it does not work with .innerHTML() to write to head. I am using jQuery 2.0.3 and jQuery UI 1.10.3.

I want to add base64 encoded script to head section. I use base64 decoder js like this to decode the javascript and then put on the head section.

//Edited
It will be

$.getScript('base64.js');
var encoded = "YWxlcnQoImhpIik7DQo="; //More text
var decoded = decodeString(encoded);
var script = '<script type="text/javascript">' +decoded + '</script>';
$('head').append(script);

To fit an encoded script and the addition in one javascript file. I want to use base64.js or some other decoder javascript files for browsers does not accept atob().

Community
  • 1
  • 1
john3825
  • 587
  • 1
  • 6
  • 14
  • 1
    have you tried `$.getScript()`? – Jai Sep 13 '13 at 11:16
  • I want to add ` – john3825 Sep 13 '13 at 12:57
  • Adding DOM elements dynamically cause unstable because they depend of browser even with `.readyState()` to check the status. Maybe `EventListner` will solve, but the all the followings are not good because of the dynamic loading tendency, [reference](http://unixpapa.com/js/dyna.html). – john3825 Sep 19 '13 at 05:43
  • See my answer below directly using a Data Url and avoiding the need to download base64.js - newScript.src = "data:text/plain;base64,YWxlcnQoImhpIik7DQo=" – Jerome WAGNER May 30 '22 at 15:44

13 Answers13

90

try this

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'url';    

document.head.appendChild(script);
Remi Guan
  • 21,506
  • 17
  • 64
  • 87
pbaris
  • 4,525
  • 5
  • 37
  • 61
18

If injecting multiple script tags in the head like this with mix of local and remote script files a situation may arise where the local scripts that are dependent on external scripts (such as loading jQuery from googleapis) will have errors because the external scripts may not be loaded before the local ones are.

So something like this would have a problem: ("jQuery is not defined" in jquery.some-plugin.js).

var head = document.getElementsByTagName('head')[0];

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js";
head.appendChild(script);

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "/jquery.some-plugin.js";
head.appendChild(script);

Of course this situation is what the .onload() is for, but if multiple scripts are being loaded that can be cumbersome.

As a resolution to this situation, I put together this function that will keep a queue of scripts to be loaded, loading each subsequent item after the previous finishes, and returns a Promise that resolves when the script (or the last script in the queue if no parameter) is done loading.

load_script = function(src) {
    // Initialize scripts queue
    if( load_script.scripts === undefined ) {
        load_script.scripts = [];
        load_script.index = -1;
        load_script.loading = false;
        load_script.next = function() {
            if( load_script.loading ) return;

            // Load the next queue item
            load_script.loading = true;
            var item = load_script.scripts[++load_script.index];
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = item.src;
            // When complete, start next item in queue and resolve this item's promise
            script.onload = () => {
                load_script.loading = false;
                if( load_script.index < load_script.scripts.length - 1 ) load_script.next();
                item.resolve();
            };
            head.appendChild(script);
        };
    };

    // Adding a script to the queue
    if( src ) {
        // Check if already added
        for(var i=0; i < load_script.scripts.length; i++) {
            if( load_script.scripts[i].src == src ) return load_script.scripts[i].promise;
        }
        // Add to the queue
        var item = { src: src };
        item.promise = new Promise(resolve => {item.resolve = resolve;});
        load_script.scripts.push(item);
        load_script.next();
    }

    // Return the promise of the last queue item
    return load_script.scripts[ load_script.scripts.length - 1 ].promise;
};

With this adding scripts in order ensuring the previous are done before staring the next can be done like...

["https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js",
 "/jquery.some-plugin.js",
 "/dependant-on-plugin.js",
].forEach(load_script);

Or load the script and use the return Promise to do work when it's complete...

load_script("some-script.js")
.then(function() {
    /* some-script.js is done loading */
});
Nickolas Hook
  • 774
  • 5
  • 13
  • This is an excellent complete solution to the overall problem, I very much appreciate you sharing. I am using it as part of a lightweight library to execute javascript code in notepad++. – Chris Mar 09 '18 at 17:02
  • Super solution and should be accepted answer i think. – lehel Apr 09 '18 at 10:41
  • Great solution when using vanilla JS, it not only saves time but is cleaner than writing and parsing redundant HTML script tags. – R. StackUser May 24 '19 at 17:04
  • are is a good article on loading scripts https://www.html5rocks.com/en/tutorials/speed/script-loading/ – JoAMoS Jul 09 '19 at 17:06
12

try out ::

var script = document.createElement("script");
script.type="text/javascript";
script.innerHTML="alert('Hi!');";
document.getElementsByTagName('head')[0].appendChild(script);
GuerraTron
  • 469
  • 4
  • 5
8

As per the author, they want to create a script in the head, not a link to a script file. Also, to avoid complications from jQuery (which provides little useful functionality in this case), vanilla javascript is likely the better option.

That may possibly be done as such:

var script = document.createTextNode("<script>alert('Hi!');</script>");   
document.getElementsByTagName('head')[0].appendChild(script);

Some clarification to those who may be confused on why this works: All code in the webpage is text. Text is the most fundamental type in a web page. The browser simply starts processing through the text, following its rules, until it reaches the end (this includes loopbacks, recursion, etc.)

For this to work, the script that makes this tag must also be in the header. The browser, when processing, will hit this code before reaching the end of the header, append the script you want onto the header, and then reach it later as it continues to process. If you had a reliable end footer, you could change out 'head' for 'footer' or similar, but considering the most reliable across sites that have scripts is the existence of the header tag, that makes it the most useful option in this case.

lilHar
  • 1,735
  • 3
  • 21
  • 35
  • createTextNode?! That'll just add your text into the head, and will not create the script tag. – Gyuri Apr 17 '20 at 23:42
  • Scripts *are* text. Notice the starting "" in my example. – lilHar Apr 21 '20 at 04:42
  • This one just add text into header, not script tag – Long Nguyen Dec 01 '21 at 02:05
  • @LongNguyen I can only assume when you tested it, you replaced ```""``` with whatever you wanted. Don't do that. Replace ONLY ```alert('Hi!');``` with the script you want, or you ran the script in the body. The thing is, the entire website is 'merely' text. Script tags *are* text. If this runs before the browser has finished processing through the header, the alert *will* fire. If you're just wanting a script to *be* there to call later, it will work. – lilHar Dec 02 '21 at 19:16
  • @lilHar No, I kept all that you wrote, not replacing anything. – Long Nguyen Dec 03 '21 at 09:57
  • Odd, it works for me. Where are you placing it? It's important to keep run order in mind. – lilHar Dec 03 '21 at 15:40
5

Best solution I've found:

AppendToHead('script', 'alert("hii"); ');
//or
AppendToHead('script', 'http://example.com/script.js');
//or
AppendToHead('style', '#myDiv{color:red;} ');
//or
AppendToHead('style', 'http://example.com/style.css');

function AppendToHead(elemntType, content) {
  // detect whether provided content is "link" (instead of inline codes)
  var Is_Link = content.split(/\r\n|\r|\n/).length <= 1 && content.indexOf("//") > -1 && content.indexOf(" ") <= -1;
  if (Is_Link) {
    if (elemntType == 'script') {
      var x = document.createElement('script');
      x.id = id;
      x.src = content;
      x.type = 'text/javascript';
    } else if (elemntType == 'style') {
      var x = document.createElement('link');
      x.id = id;
      x.href = content;
      x.type = 'text/css';
      x.rel = 'stylesheet';
    }
  } else {
    var x = document.createElement(elemntType);
    if (elemntType == 'script') {
      x.type = 'text/javascript';
      x.innerHTML = content;
    } else if (elemntType == 'style') {
      x.type = 'text/css';
      if (x.styleSheet) {
        x.styleSheet.cssText = content;
      } else {
        x.appendChild(document.createTextNode(content));
      }
    }
  }
  //append in head
  (document.head || document.getElementsByTagName('head')[0]).appendChild(x);
}
biberman
  • 5,606
  • 4
  • 11
  • 35
T.Todua
  • 53,146
  • 19
  • 236
  • 237
3
var script = $('<script type="text/javascript">// function </script>')
document.getElementsByTagName("head")[0].appendChild(script[0])

But in that case script will not be executed and functions will be not accessible in global namespase. To use code in <script> you need do as in you question

$('head').append(script);

Dmitry Masley
  • 525
  • 4
  • 9
  • This answer unexpectedly helped me. A third-party script was checking for the existence of my added script by actually looking for the – Eric N Apr 06 '16 at 21:33
2

This is an old question, and I know its asking specifically about adding a script tag into the head, however based on the OPs explanation they actually just intend to execute some JS code which has been obtained via some other JS function.

This is much simpler than adding a script tag into the page.

Simply:

eval(decoded);

Eval will execute a string of JS in-line, without any need to add it to the DOM at all.

I don't think there's ever really a need to add an in-line script tag to the DOM after page load.

More info here: http://www.w3schools.com/jsref/jsref_eval.asp

undefined
  • 33,537
  • 22
  • 129
  • 198
2

If you want to add a script tag with some script inside, use

var script= document.createElement('script');
script.text = "alert('Hi!');";
document.head.appendChild(script);
Long Nguyen
  • 9,898
  • 5
  • 53
  • 52
1

you could do:

var scriptTag = document.createElement("script");
scriptTag.type = "text/javascript";
scriptTag.src = "script_source_here";
(document.getElementsByTagName("head")[0] || document.documentElement ).appendChild(scriptTag);
Sudhir Bastakoti
  • 99,167
  • 15
  • 158
  • 162
  • I want to add `` to the head for using a base64 encoded script and put them in one files as I added the details. – john3825 Sep 13 '13 at 12:25
1

I use PHP as my serverside language, so the example i will write in it - but i'm sure there is a method in your server side as well.

Just have your serverside language add it from a variable. w/ php something like that would go as follows.

Do note, that this will only work if the script is loaded with the page load. If you want to load it dynamically, this solution will not help you.

PHP

HTML

<head>
    <script type="text/javascript"> <?php echo $decodedstring ?> </script>
</head>

In Summary: Decode with serverside and put it in your HTML using the server language.

pbaris
  • 4,525
  • 5
  • 37
  • 61
Ulad Kasach
  • 11,558
  • 11
  • 61
  • 87
1

Here is a safe and reusable function for adding script to head section if its not already exist there.

see working example here: Example

<!DOCTYPE html>
<html>
  <head>
    <base href="/"/>
    <style>
    </style>
  </head>
  <body>
    <input type="button" id="" style='width:250px;height:50px;font-size:1.5em;' value="Add Script" onClick="addScript('myscript')"/>
    <script>
      function addScript(filename)
      {
        // house-keeping: if script is allready exist do nothing
        if(document.getElementsByTagName('head')[0].innerHTML.toString().includes(filename + ".js"))
        {
          alert("script is allready exist in head tag!")
        }
        else
        {
          // add the script
          loadScript('/',filename + ".js");
        }
      }
      function loadScript(baseurl,filename)
      {
        var node = document.createElement('script');
        node.src = baseurl + filename;
        document.getElementsByTagName('head')[0].appendChild(node);
        alert("script added");
      }
    </script>
  </body>
</html>
Jonathan Applebaum
  • 5,738
  • 4
  • 33
  • 52
1
<script type="text/JavaScript">
     var script = document.createElement('SCRIPT');
    script.src = 'YOURJAVASCRIPTURL';
    document.getElementsByTagName('HEAD')[0].appendChild(script);
 </script>
1

You can directly use a "Data URL". Using the data in your example:

var newScript = document.createElement("script");
newScript.type = "text/javascript";
document.head.appendChild(newScript);
newScript.src = "data:text/plain;base64,YWxlcnQoImhpIik7DQo="

This way, you can skip loading base64.js and directly evaluate the base64 encoded script.

Jerome WAGNER
  • 21,986
  • 8
  • 62
  • 77