skip to Main Content

I have a weird issue where I’m using jQuery to automatically add an "active" class to an internal menu (and update the url on) when the user scrolls or clicks on each menu item. On scroll it works fine, but on click it bolds and updates the url for the item ABOVE the item clicked, and I can’t figure out why…

I have a menu set up like this:

<ul>
<li><a href="#1" data-id="1" class="toc-link">link 1</a></li>
<li><a href="#2" data-id="2" class="toc-link">link 2</a></li>
...etc
</ul>

And content set up as:

<h2 id="1">title 1<h2>
<p>content</p>
<h2 id="2">title 2<h2>
<p>content</p>
...etc

jQuery script:

jQuery(document).ready(function() {
  // Update the active header and URL on click
  jQuery('.toc-link').click(function(e) {
    e.preventDefault();
    var activeId = jQuery(this).attr('data-id');
    var url = window.location.href.split('#')[0];
    var newUrl = url + '#' + activeId;
    window.history.pushState('', document.title, newUrl);

    jQuery('.toc-link.active').removeClass('active');
    jQuery(this).addClass('active');
    
    // Scroll to corresponding header
    var headerTop = jQuery('#' + activeId).offset().top;
    jQuery('html, body').animate({ scrollTop: headerTop }, 500);
  });

  // Update the active header and URL on scroll
  jQuery(window).scroll(function() {
    var scrollPos = jQuery(window).scrollTop();
    var activeId = null; // Initialize activeId to null

    jQuery('h2').each(function() {
      var headerTop = jQuery(this).offset().top;
      var id = jQuery(this).attr('id');

      if (scrollPos >= headerTop) {
        activeId = id;
      }
    });

    if (activeId !== null) {
      var newUrl = window.location.href.split('#')[0] + '#' + activeId;
      window.history.pushState('', document.title, newUrl);

      jQuery('.toc-link').removeClass('active'); // remove active class from all links
      jQuery('.toc-link[data-id="' + activeId + '"]').addClass('active'); // add active class to matching link
    }
  });
});

You can see this problem in action here.

I feel like this is a simple fix, but my javascript isn’t that great. I’d appreciate any pointers. Thanks!

2

Answers


  1. Chosen as BEST ANSWER

    So to make a long story short, the problem seems to be with the way I'm scrolling the page. Although there are probably better solutions, this is what I came up with - taking 100 off of the headerTop variable:

        var headerTop = jQuery(this).offset().top;
        var headerTop = headerScrollTop - 100;
    

  2. I observed in the console

    enter image description here

    while click on tag your data-id is very weird for me like below:

    activeId = ‘1-%D7%94%D7%9C%D7%94%D7%A7%D7%95%D7%AA-%D7%91%D7%A7%D7%95%D7%9E%D7%93%D7%99%D7%94-%D7%93%D7%9C%D7%B3%D7%90%D7%A8%D7%98%D7%94’

    can you check your active-Id because you have passed numeric ID in that attribute.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search