3

How do I get the jQuery function show below to wait until the DOM has loaded before it's read? I thought that specifying "$(document).ready(function..." at the beginning of the function declaration would do the trick but when my page executes, the function doesn't work and I can see the message "Uncaught ReferenceError: $ is not defined" in my browser's developer console.

This is my base template:

# base.html
<!DOCTYPE html>
<html>
...
<body>
{% block page_container %} {% endblock %}
...
<script src="https://code.jquery.com/..."></script>
<script src="js/bootstrap.min.js"></script>
...
</body>
</html>

This Django template extends (is enclosed by) the base template:

# upload_file.html
{% extends base.html %}

(HTML for form ...)
<label class="btn btn-success btn-file">
    Select Photo <input type="file" name="photo" style="display: none;">
</label>
(more HTML...)

<script>
    $(document).ready(function() {

      $(document).on('change', ':file', function() {
        var input = $(this),
            numFiles = input.get(0).files ? input.get(0).files.length : 1,
            label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
        input.trigger('fileselect', [numFiles, label]);
      });

      $(document).ready( function() {
          $(':file').on('fileselect', function(event, numFiles, label) {

              var input = $(this).parents('.input-group').find(':text'),
                  log = numFiles > 1 ? numFiles + ' files selected' : label;

              if( input.length ) {
                  input.val(log);
              } else {
                  if( log ) alert(log);
              }

          });
      });

    });
</script>

Of course, if I move the script tag that calls jQuery up inside the block in my base template, the function executes. However, I'd prefer to keep my jQuery script element at the bottom of my base template as is illustrated in the Bootstrap documentation. Is there a way to get this function to work if jQuery is referenced after the function that calls it in my page?

Thanks.

-- FOLLOW-UP --

I credited fyrb with the answer since he answered first and I ended up doing what he proposed, but I appreciated the other answers too. I'm adding links to some good posts on this subject below for the benefit of others who have this question. There are some good performance reasons for putting your jquery call at the end of the page as will be seen in these articles.

Community
  • 1
  • 1
Jim
  • 11,270
  • 21
  • 86
  • 134

3 Answers3

1

Essentially it boils down to the fact that you need to include jQuery before using its methods.

Typically you would have your

<script src="https://code.jquery.com/..."></script>
<script src="js/bootstrap.min.js"></script>

In the html <head> tag

I'm less familiar with Django, but is there a reason why you wouldn't want jQuery and bootstrap in the document head?

In any case, you need to include those scripts before your code.

Otherwise, you can take a look at this: $(document).ready equivalent without jQuery

fyrb
  • 71
  • 5
1

Normally it is best practice to put js scripts in the bottom because it lock up the page load. But when it comes to jQuery it is best to put it right after style and the rest of script can be at the bottom.

To solve your problem all you have to do is move jQuery import before you use the $ variable. It caused an error because at that time $ does not exist yet.

# base.html
<!DOCTYPE html>
<html>
...
<script src="https://code.jquery.com/..."></script>    <!-- move this line here -->
</head>
<body>
{% block page_container %} {% endblock %}
...
<script src="js/bootstrap.min.js"></script>
...
</body>
</html>
Du D.
  • 3,819
  • 1
  • 24
  • 31
0

Since you are using $(document).ready function, essentially you are trying to access $ (jquery variable which is not loaded)

So one solution can be to load jquery in head and rest of your javascript files can reside at bottom of page and all JS code can then be added at .ready event.

But if you want to embed even jQuery in the footer, then you can use multiple methods of doing so as showcased well in answer to below question:

pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it

One which i prefer:

<script>
// self executing function here
(function() {
   // your page initialization code here
   // the DOM will be available here

})();
</script>

Recommendation:

But what i recommend is to use atleast jquery in head with other components in page and rest of JS files can be then loaded in end of page. Since jquery is a very important component of page and other internal/external components might have a dependency over it. Rest is upon your use case and implementation.

Community
  • 1
  • 1
abhinsit
  • 2,962
  • 4
  • 16
  • 24