Vincent
Vincent

Reputation: 270

Calling javascript in javascript works for some but not all scripts

I have the following code in a script.js file that I call in my html file:

function loadScript(url)
{    
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    script.async = false;
    head.appendChild(script);
}

loadScript('https://polyfill.io/v3/polyfill.min.js?features=es6')
loadScript('https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js')
loadScript('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js')

hljs.initHighlightingOnLoad();

I use this code because I want to call only one .js file in my html instead of multiple .js files.

The first two scripts that I load to call MathJax work fine. The third script to call highlight.js however does not run.

When I paste all the code from the file 'highlight.min.js' into the my script.js file, the javascript does run normally when I open the html.

I don't understand why loading the 'highlight.min.js' file with the loadScript() does not work, or what I can do to get it to work. Any help is appreciated.

Upvotes: 3

Views: 104

Answers (2)

The script loading is asyncronous, so when hljs.initHighlightingOnLoad() is called the scripts are not loaded yet.

Alternative 1

You can modify your loadScript() function to make it work with promises, which resolve when the script is loaded (taken from here):

function loadScript(url) {    
    return new Promise(function(resolve, reject) {
        var script = document.createElement("script");
        script.onload = resolve;
        script.onerror = reject;
        script.src = url;
        document.getElementsByTagName("head")[0].appendChild(script);
    });
}

Now you can call your code and be sure that all libraries are loaded before calling hljs.initHighlightingOnLoad():

(async function init() {
  await loadScript('https://polyfill.io/v3/polyfill.min.js?features=es6');
  await loadScript('https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js')
  await loadScript('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js')
  
  hljs.initHighlightingOnLoad();
})()

Alternative 2

You can modify your loadScript() function to make it load the scripts using defer and add an optional onload handler that you can use to call hljs.initHighlightingOnLoad():

function loadScript(url, onload)
{    
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    script.async = false;
    script.onload = onload;
    head.appendChild(script);
}

loadScript('https://polyfill.io/v3/polyfill.min.js?features=es6')
loadScript('https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js')
loadScript('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js', () => {hljs.initHighlightingOnLoad()})

Upvotes: 2

Jay
Jay

Reputation: 3355

Wheres your onload handler?

script.onload = function(){};

Lets not worry about errors for now...

https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement

If the libs require each other then you need to defer because the child may be smaller than the parent.

Upvotes: 1

Related Questions