88

I have a html page where I am appending html at dynamically through a javascript like below

<script type="text/javascript" src="/myapp/htmlCode"></script>

I want to call a js function e.g. loadedContent(); once the above script adds dynamic html.

Can someone help me how I can do that?

Neeraj
  • 1,576
  • 1
  • 14
  • 33

8 Answers8

147

you can achieve this without using head.js javascript.

function loadScript( url, callback ) {
  var script = document.createElement( "script" )
  script.type = "text/javascript";
  if(script.readyState) {  // only required for IE <9
    script.onreadystatechange = function() {
      if ( script.readyState === "loaded" || script.readyState === "complete" ) {
        script.onreadystatechange = null;
        callback();
      }
    };
  } else {  //Others
    script.onload = function() {
      callback();
    };
  }

  script.src = url;
  document.getElementsByTagName( "head" )[0].appendChild( script );
}


// call the function...
loadScript(pathtoscript, function() {
  alert('script ready!'); 
});
Cristian Traìna
  • 7,056
  • 1
  • 31
  • 51
Jaykesh Patel
  • 1,782
  • 1
  • 12
  • 16
  • 7
    FYI: `onload` is ok for IE versions 9 and later - so just setting `onload` is probably ok for most people now – Simon_Weaver Feb 20 '17 at 07:08
  • 4
    Note `onload` will start the callback the minute the script "LOADS" not when its actually finished execution, which is disappointing – Ma Dude Aug 13 '18 at 21:20
  • @MaDude Can you refer to any documentation regarding that? – kontrollanten Nov 07 '18 at 11:25
  • 2
    The `onload` handler couldn't possibly be called when the script hasn't finished execution, because Javascript is single threaded. This means the `onload` handler could only be called either BEFORE the script start's execution or AFTER it has finished execution. I personally have never seen the former case to occur...EVER. If anyone knows about a reproducible case where the `onload` handler can be called BEFORE the script starts executing, please tell us. – GetFree Feb 12 '19 at 18:50
  • A simple extension to load an array of scripts: ```function loadScripts (urls, callback) {var counter = 0 for (var i=0; i – sree May 05 '20 at 17:49
32

I had the same problem... My solution (without jQuery) :

<script onload="loadedContent();" src ="/myapp/myCode.js"  ></script>
Didier68
  • 756
  • 8
  • 18
  • 2
    Please note: This will not be compatible with strict CSPs. – Bradley May 03 '20 at 06:56
  • @Bradley are you sure? I guess that addig the `nonce="${nonce}"` should make it work (untested guess). – guettli Apr 15 '21 at 19:08
  • @guettli Nope, unfortunately you can't nonce an inline event-handler. Only element contents are "nonceable", so execution would fail if you tried using the OPs attribute with a strict CSP. – Bradley Apr 25 '21 at 03:15
20

If you're reading this post in 2021, probably you're more used to Promises. A more modern approach is preferable if either all your target browsers support ES6 or you are using a polyfill.

This solution works like @JaykeshPatel answer, but it's based on Promises:

// definition
function loadScript(scriptUrl) {
  const script = document.createElement('script');
  script.src = scriptUrl;
  document.body.appendChild(script);
  
  return new Promise((res, rej) => {
    script.onload = function() {
      res();
    }
    script.onerror = function () {
      rej();
    }
  });
}

// use
loadScript('http://your-cdn/jquery.js')
  .then(() => {
    console.log('Script loaded!');
  })
  .catch(() => {
    console.error('Script loading failed! Handle this error');
  });

You can pass some contextual variables in arguments of the res callback, or if your library imported some global symbol, you can reference it there.

For example, since jQuery introduces the $ global symbol, you can call res($) and create a local scope for it (perfect if you are using TypeScript and you don't want to declare a module variable in each file, in this way you can write const $ = await loadScript(..)).

If you don't mean to pass any argument, you can just shorten your code like this:

script.onload = res;
script.onerror = rej;
Cristian Traìna
  • 7,056
  • 1
  • 31
  • 51
  • 1
    `script.onLoad = res;` // simplify – Kunukn Feb 01 '19 at 09:30
  • 1
    @Kunukn there is also a shorter one `return new Promise(res => script.onload = res)`. But assigning a function to `onload` can be easier to read and allows you to pass an argument on resolve – Cristian Traìna Feb 01 '19 at 09:50
12

try something like this

var script = document.createElement('script');

if(script.readyState) {  //IE
script.onreadystatechange = function() {
  if ( script.readyState === "loaded" || script.readyState === "complete" ) {
    script.onreadystatechange = null;
    alert(jQuery);
  }
};
 } else{//others
script.onload = function() {
  alert(jQuery); 
}
}
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"
document.documentElement.appendChild(script);
Bellash
  • 5,719
  • 3
  • 39
  • 72
socm_
  • 711
  • 10
  • 22
4

actually you could just put the loadedContent() as the last line of the script you're loading (which is kind of the concept behind JSONP)

David Fregoli
  • 3,282
  • 1
  • 16
  • 37
4

My answer is an extension of the Jaykesh Patel answer. I've implemented this code in order to load multiple javascript. Hope this helps someone:

// RECURSIVE LOAD SCRIPTS
function load_scripts( urls, final_callback, index=0 )
{
    if( typeof urls[index+1] === "undefined" )
    {
        load_script( urls[index], final_callback );
    }
    else
    {
        load_script( urls[index], function() {
            load_scripts( urls, final_callback, index+1 );
        } );
    }
}

// LOAD SCRIPT
function load_script( url, callback )
{
    var script = document.createElement( "script" );
    script.type = "text/javascript";
    if(script.readyState) // IE
    {
        script.onreadystatechange = function()
        {
            if ( script.readyState === "loaded" || script.readyState === "complete" )
            {
                script.onreadystatechange = null;
                callback();
            }
        };
    }
    else // Others
    {  
        script.onload = function() { callback(); };
    }
    script.src = url;
    document.getElementsByTagName( "head" )[0].appendChild( script );
    debug("javascript included: "+url);
}

// EXAMPLE  
var main = function()
{
    console.log("main function executed");
}
var js = [ "path/to/script-1", "path/to/script-2", "path/to/script-3" ];
load_scripts( js, main );
Marco Panichi
  • 968
  • 1
  • 17
  • 27
1

Check out head.js. It will achieve what you're after, providing callbacks when your file(s) have successfully loaded and executed.

CherryFlavourPez
  • 6,807
  • 4
  • 42
  • 47
-3
  $.getScript("your script",function () {
      "your action";
  });