0

I have a $(document).ready function (shows the mobile menu) which has to wait for the jQuery import. I noticed that sometimes it shows up and sometimes it doesn't depending if jQuery loads first. The jQuery import loads asynchronously. I wanted to delay the $(document).ready function until it's sure that jQuery is already loaded. I tried using defer and async but it doesn't seem to work. I also tried adding setTimeout() but it doesn't work too.

<script async='async' src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js' type='text/javascript' /> <script defer='defer' async='async' type='text/javascript'> ;(function ($, document, window) { var // default settings object. defaults = { label: 'MENU', duplicate: true, duration: 200, easingOpen: 'swing', easingClose: 'swing', closedSymbol: '&#9658;', openedSymbol: '&#9660;', prependTo: 'body', parentTag: 'a', closeOnClick: false, allowParentLinks: false, nestedParentLinks: true, showChildren: false, init: function(){}, open: function(){}, close: function(){} },... </script> 
4
  • async attribute is only relevant to external scripts, i.e. no effect on inline - defer attribute, according to MDN, "should only be used on external scripts" - Commented Feb 17, 2017 at 2:26
  • I was thinking that it doesn't work for inline scripts but I just tried it to see. Is there a way for me to have the inline script wait for the jQuery import? Commented Feb 17, 2017 at 2:28
  • try using onload="someFunc()" in the jQuery script tag, and wrapping the code you have in function someFunc() { ... your code ... } Commented Feb 17, 2017 at 2:31
  • I don't see a document.ready() there. Commented Feb 17, 2017 at 3:04

2 Answers 2

2

The problem is that you're loading jQuery as async:

<script async='async' <----------- this is the problem src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js' type='text/javascript' /> 

The async property tells your browser that it's OK to load this file later after executing all other javascript code on the page. The solution is to remove the async.

But isn't async recommended?

Yes but only for scripts that other scripts on your page don't depend on. For libraries like jQuery where you need to be certain has been loaded you should not use async.

But wouldn't it slow down page load if the browser waits for jQuery?

Yes, the solution to this is to move all your script tag to the bottom of the page, outside <head>, just before the closing of the <body> tag:

<html> <head></head> <body> some stuff... <script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js' type='text/javascript' /> <script type='text/javascript'> ;(function ($, document, window) { var // default settings object. defaults = { label: 'MENU', duplicate: true, duration: 200, easingOpen: 'swing', easingClose: 'swing', closedSymbol: '&#9658;', openedSymbol: '&#9660;', prependTo: 'body', parentTag: 'a', closeOnClick: false, allowParentLinks: false, nestedParentLinks: true, showChildren: false, init: function(){}, open: function(){}, close: function(){} },... </script> </body> </html> 

But I (or my boss) don't like script outside of head!!

Well, you can still have your script in head but it's a bit involved. Basically you need to listen to the onload event of the jquery script tag. But that means you need to create the tag dynamically instead of hardcoding it in html:

<html> <head> <script> var jq = document.createElement('script'); jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"; jq.async = true; // you can still load as async! jq.onload = function () { (function ($, document, window) { var // default settings object. defaults = { label: 'MENU', duplicate: true, duration: 200, easingOpen: 'swing', easingClose: 'swing', closedSymbol: '&#9658;', openedSymbol: '&#9660;', prependTo: 'body', parentTag: 'a', closeOnClick: false, allowParentLinks: false, nestedParentLinks: true, showChildren: false, init: function(){}, open: function(){}, close: function(){} },... }; document.head.appendChild(jq); </script> </head> <body> .... </body> </html> 
Sign up to request clarification or add additional context in comments.

3 Comments

For the 2nd approach, should I only place all the scripts in the head? I tried it in the body but it seems that the other scripts are showing errors.
@Vinz: What errors? If they don't depend on jQuery then there's no reason they would error if jQuery is moved to the body. Heck, you can even remove jQuery completely and they should continue to work. If they depend on jQuery then you need to move them ALL to the body. FYI, both Yahoo and Google page speed test recommend NOT putting js in head but put them at the bottom of body instead
I just did the first approach. Thanks!
0

Put your $(document).ready function as the last script on your page.

And you might want to consider putting the script which loads JQuery in the <head> of your document to make sure it loads before it is called.

2 Comments

He's already doing that. The problem is he's loading jQuery as async (see his script tag) which tells the browser that it's OK to execute code after the tag first without waiting for jQuery to finish loading
Yes, the script is already at the bottom before the closing of the body.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.