0

On my HTML page, I have the following way of loading JS files:

<script id="jjquery"></script>
<script id="jscookie"></script>
<script id="winx"></script>

<script>
(function(){
  if(screen.width > 479) 
    document.querySelector("#jjquery").setAttribute("src", "/js/jquery-3.3.1.min.js");
    document.querySelector("#jscookie").setAttribute("src", "/js/jscookie.js");
    document.querySelector("#winx").setAttribute("src", "/js/winx.js");
}());
</script>

Basically I used the way described in this answer to only load certain scripts starting from the specific screen resolution. But the third script out of three, that relies on jquery, is not working and says $ is not defined. Even though if I enter $ in the console, it returns normal response. And when I see the order of the scripts in the HTML output, it is clear that jquery is loaded prior to two other scripts. What could be the issue here?

P.S. everything works comlpetely fine if I just load the scripts normally without the resolution check.

Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
COOLak
  • 379
  • 3
  • 15
  • When you change the `src`, there is a delay to load it. You will have to use a `load` event. – Louys Patrice Bessette Feb 05 '19 at 21:26
  • Thank you, but I don't know how to use it. Would you please create an answer showing it? P.S. it mustn't rely on jquery. – COOLak Feb 05 '19 at 21:31
  • 2
    Possible duplicate of [conditionally load javascript (external and internal) and keep execution order](https://stackoverflow.com/questions/3973441/conditionally-load-javascript-external-and-internal-and-keep-execution-order) – Heretic Monkey Feb 05 '19 at 21:32

1 Answers1

0

The problem is that the scripts are loaded asynchronously, so the order of your code isn't relevant.

You can see a MDN example of how you can properly import your scripts.

In your case, if some of your scripts depend on jquery, you can create an onLoadJquery function and append it as the onload attribute of the script, this function will be executed after the import.

<script>
(function(){
  if(screen.width > 479) { 
    // add the callback that will be executed once jquery is loaded
    document.querySelector("#jjquery").addEventListener("load", onLoadJquery);
    document.querySelector("#jjquery").setAttribute("src", "/js/jquery-3.3.1.min.js");
    document.querySelector("#jscookie").setAttribute("src", "/js/jscookie.js");

  }

  function onLoadJquery() {
    // safely import the rest of the scripts
    document.querySelector("#winx").setAttribute("src", "/js/winx.js");
  }
}());
</script>
Rodrigo Ferreira
  • 1,091
  • 8
  • 11
  • 1
    Why set an HTML attribute to add an event handler? You could just use `document.querySelector("#jjquery").addEventHandler("load", onLoadJquery)`... – Heretic Monkey Feb 05 '19 at 21:34
  • @HereticMonkey it has been the standard since the beginning, `addEventListener` is supported since IE9, of course you can use it too. – Rodrigo Ferreira Feb 05 '19 at 21:52
  • If I use Rodrigo Ferreira's code, my jquery-dependent script just doesn't work, without any errors or anything. If I use the line from Heretic Monkey instead, it throws an error `document.querySelector(...).addEventHandler is not a function` (on Firefox 65). – COOLak Feb 05 '19 at 22:02
  • @ErikGordon I think Heretic Monkey was referring to `addEventListener` – Rodrigo Ferreira Feb 05 '19 at 22:05
  • 1
    Indeed, it worked now. Thank you both. Neither I would be able to come up with a search request like that to find that other question, nor I would be able to apply the answer from there to my case. – COOLak Feb 05 '19 at 22:14
  • @RodrigoFerreira if you edit your answer and replace `document.querySelector("#jjquery").setAttribute("onload", onLoadJquery);` with `document.querySelector("#jjquery").addEventListener("load", onLoadJquery);`, I'll choose it as accepted, because your original answer didn't work. – COOLak Feb 05 '19 at 22:18
  • 1
    @ErikGordon I applied the change that you suggested – Rodrigo Ferreira Feb 05 '19 at 22:21