0

When using an importjs() type of function (see below for an example), jQuery doesn't seem to be loading before the code following it.

Here's a sample html file:

<html>
  <head></head>
  <body>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript">
      function importjs(jsFile) {
        var body = document.getElementsByTagName('head').item(0);
        var scpt = document.createElement('script');
        scpt.src = jsFile;
        scpt.type = 'text/javascript';
        body.appendChild(scpt);
      }
      var f1="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js";
      //importjs(f1);
      var $j=jQuery;
      alert("hello stackoverflow!");
    </script>
  </body>
</html>

With the above code, the alert should successfully fire.

Next, comment out the first script block, i.e. the one explicitly loading jQuery, and uncomment the importjs(f1) line in the second script block. This time, the alert does not fire, at least in firefox and safari.

Now, put in an extra alert before the line "var $j=jQuery". For me, it works in both browsers, regardless of how long or short I wait. A setTimeout would probably also do the trick, but it's also not an ideal way to program something like this.

If javascript is single-threaded, why does the importjs fail? Is it because the new element created by importjs doesn't get 'executed' until the first block finishes, or should the new element be executed as soon as it is created?

1 Answer 1

7

There are several problems here:

  • you have jQuery duplicated, one in the html, one in the js
  • dynamically added javascript won't be available immediately if you load scripts this way the dependant code should be in a callback function

    function importjs(jsFile, callback) {
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.src = jsFile;
        script.type = 'text/javascript';
        script.onload = script.onreadystatechange = function() {
          // execute callback
          if (callback) callback();
          // prevent memory leak in IE
          script.onload = null;
          head.removeChild(script);
        };
        head.appendChild(script);
    }
    

    then you should use it as:

    importjs("jquery.js", function(){
        // all jQuery dependant code
        // goes here...
    });​
    

UPDATE

There is a more robust solution for including javascript files which allows you to:

  • include multiple files that are related
  • ensure they are executed in order
  • load them in a non-blocking way (parallel with other resources)

I'm still working on this script, but pretty much works right now. Be sure to check it out.

It combines the advantages of different techniques to give a huge benefit on page load time. Here is a related article: Loading Scripts Without Blocking

The syntax is:

include(['jquery.js','jquery-ui.js'], myjQueryCode); // executed in order
Sign up to request clarification or add additional context in comments.

6 Comments

Not sure I get your first point - I think there is only a duplication if you uncomment the importjs. But your main contribution (changing "script.onload" to "scpt.onload") did the trick. Thanks!!!!!
yes I was talking about that duplication. if you remove your html script tag you're good to go.
update: it works on every browser I've tried except for IE (I've only tested on IE8 so far). Any further suggestions?
alright, I've forgot the IE specific part. Updated the answer. Now it works.
You rock! Works like a charm! Two more questions: 1) do you grant a license to me to use this script in my code? 2) is there a simpler way to do a simpler version of this question: I want to create a widget includable on any webpage. So far, the only code I need for this falls in two libraries: mine and jQuery, but I need to make sure jQuery loads before my code runs. Your code will work for this but seems a bit excessively nice/powerful for it. Also, I will have no control over the jQuery version on the rest of the page, so I want to avoid version conflicts. Thoughts?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.