Search code examples
javascripthtmljquerynavbarbootstrap-5

.addClass fails to apply to HTML imported with .load when using jQuery?


I am creating a navbar which disappears when the user scrolls down, and reappears if the user scrolls up. I would also like to keep the navbar's code in its own HTML file, to make it easier to edit.

.load

The navbar code is included like this in the index.html file:

 <div id="nav"></div>

The JavaScript to load this is included in the <script> of the index.html file:

  $(function(){
      $("#nav").load("navbar.html");
  }); 

This works!

.addClass

I am also using the following jQuery function to allow my navbar to appear and disappear as the user scrolls up and down:

(function ($) {
var previousScroll = 20;
$(window).scroll(function(e) {
    var scroll = $(window).scrollTop();
    if (scroll >= previousScroll) {
        $('.navbar').addClass("navbar-hide");
    }else if (scroll < previousScroll) {
        $('.navbar').removeClass("navbar-hide");
    }
    previousScroll = scroll;
});
})(jQuery);

This code works when I include the navbar element directly in the index.html file:

  <nav class="navbar navbar-expand-sm sticky-top">
    <div class="container-fluid">
      <a class="navbar-brand" href="#">Text here</a>
      [and so on]
    </div>
  </nav>

So, when I'm not trying to include the navbar from another file, the classes can be added and removed with no errors.

Problems

I only have issues when I try to combine these two functions.

Currently, when I attempt to load the navbar from its separate file and try to apply the jQuery code, the navbar appears at the top of the page but is static. It does not follow the window when the user scrolls, even though the position in its source is sticky-top.

Fix 1? (no change)

I thought this might be because the scrolling code was being applied before the navbar was properly imported. So, I tried combining the .addClass and .load functions into a single callback function, where the loaded HTML code is loaded first, then the .addclass is applied to it. Unfortunately this gave me the same issue as the uncombined functions did. I'm new to JavaScript, so it's very possible that this function has been butchered:

$(function(){
$("#nav").load("/navbar.html", (function ($) { // the entire jQuery was inserted here:
    var previousScroll = 20;
    $(window).scroll(function(e) {
        var scroll = $(window).scrollTop();
        if (scroll >= previousScroll) {
            $('.navbar').addClass("navbar-hide");
    }else if (scroll < previousScroll) {
        $('.navbar').removeClass("navbar-hide");
    }   
    previousScroll = scroll;
});
})(jQuery));
}); 

Fix 2 (success, but...)

I also tried slightly altering the way I call the navbar file. Since the class needs to be added to the <nav> element, I tried altering my code so that only the <nav> element needed to be in index.html:

The JavaScript was updated to:

  $(function(){
      $(".navbar").load("navbartest.html");
  }); 

The new navbartest.html has no longer contained the <nav> element:

    <div class="container-fluid">
      <a class="navbar-brand" href="#">Text here</a>
      [and so on]
    </div>

and index.html now had:

    <nav class="navbar navbar-expand-lg sticky-top"></nav>

which replaced <div id="nav"></div>.

This worked! Because the <nav> element didn't have to be loaded from the other page, the jQuery function was able to apply the new classes no problem.

However, this means that any changes to the <nav> element (like changing navbar-expand-lg to navbar-expand-md) would require me to go to every single webpage file in order to update it, which is what the .load function was trying to avoid in the first place.

So, I am hoping to find a solution that allows me to keep the entirely of the navbar code in its own file. Maybe I just messed up the callback function badly?


Solution

  • While I could not figure out event delegation, I did find a fix that worked for me!

    I changed the script in the head to the following, replacing the .addClass and the .load scripts with an external reference:

        <script src="templates\navbarscript.js"></script>
    

    I moved both the .addClass and the .load functions to that new file, navbarscript.js.

    Here's the new script, located externally:

    //.load
    $(function(){ 
        $("nav").load("../templates/navbar.html"); 
        $("nav").addClass("navbar fixed-top navbar-expand-lg"); // new code!
    }); 
    
    //.addClass
    (function ($) {
      var previousScroll = 20;
      $(window).scroll(function(e) {
        var scroll = $(window).scrollTop();
        if (scroll >= previousScroll) {
          $('.navbar').addClass("navbar-hide");
        }else if (scroll < previousScroll) {
          $('.navbar').removeClass("navbar-hide");
        }
        previousScroll = scroll;
      });
    })(jQuery); 
    

    The new line of code I added is an additional .addClass. Now, when I change the classes applied to the <nav> element in this single file, it gets applied to every file with the <nav> element.

    An example of the completed HTML file is:

    <!DOCTYPE html>
    <html>
    <head>
    [...]
        <script src="templates\navbarscript.js"></script>
    </head>
    <body>
      <nav></nav>
      <div class="container">[...]</div>
      <div id="foot"></div>
    </body>
    </html>