I have the following html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/blazy/1.8.2/blazy.min.js" defer></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.9.0/js/lightbox.min.js" defer></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous" defer></script>
<!-- 26 dec flexslider js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/flexslider/2.6.3/jquery.flexslider.min.js" defer></script>
<script defer>
(function($) {
$(document).ready(function() {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
});
})(jQuery);
</script>
</head>
<body>
</body>
</html>
I get an error, saying jQuery is not defined. Now even if I remove defer from my inline JS code, it says jQuery is undefined. For some reason I have to keep the jQuery plugins in the head and keep my JS code inline. My question is:
Why doesn't inline Javascript code get deferred when defer
attribute is present on it?
Is there a way to imitate the defer behavior on my inline Javascript code? I can put that at the end of body tag if required.
The scripts with the defer
attribute load in the order they are specified, but not before the document itself has been loaded. As defer
has no effect on script
tags unless they also have the src
attribute, the first script that gets executed is your inline script. So at that time jQuery is not loaded yet.
You can solve this in at least two ways:
Put your inline script in a .js
file and reference it with a src
attribute (in addition to the defer
attribute which you already had there), or
Let your inline script wait for the document and the deferred scripts to be loaded. The DOMContentLoaded
event will fire when that has happened:
<script>
window.addEventListener('DOMContentLoaded', function() {
(function($) {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
})(jQuery);
});
</script>
NB: Notice that in the latter case $(document).ready(function()
is not included any more, as that would wait for the same event (DOMContentLoaded
). You could still include it like you had in your original code, but then jQuery would just execute the callback immediately, which makes no practical difference.