12

Does anyone know how to use scrollspy without using bootstrap? I am trying to get this to work in one of my projects using this repository:

https://github.com/sxalexander/jquery-scrollspy

but it just doesn't do what the bootstrap one does. The li tags are not marked as active :( Any help would be appreciated.

I have tried doing this:

    $('#intel_nav').scrollspy({
        //n: $('#nav').offset().top,
        onEnter: function (element, position) {
            console.log(element);

            $("#intel_nav").addClass('moo');
        },
        onLeave: function (element, position) {
            $("#intel_nav").removeClass('out');
        }
    });

The element appears to be the actual menu, so I have no idea how to actually get the id of the element I am currently hovering over.

Turnip
  • 33,774
  • 14
  • 81
  • 102
r3plica
  • 11,412
  • 17
  • 75
  • 203

5 Answers5

16

If anyone is still interested in this, I couldn't get the bootstrap scrollspy to work quickly enough so I wrote my own (technically inefficient, but simple) solution.

Here's a demo:

$(window).bind('scroll', function() {
    var currentTop = $(window).scrollTop();
    var elems = $('.scrollspy');
    elems.each(function(index){
      var elemTop  = $(this).offset().top;
      var elemBottom  = elemTop + $(this).height();
      if(currentTop >= elemTop && currentTop <= elemBottom){
        var id   = $(this).attr('id');
        var navElem = $('a[href="#' + id+ '"]');
    navElem.parent().addClass('active').siblings().removeClass( 'active' );
      }
    })
}); 
.active{
  color: red;
  background-color: red;
}

#nav{
  position:fixed;
  top:0;
  right:50%;
}

section{
  min-height: 500px;
}
<html>
 <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
   </head>
   <body>
      <nav id="nav" class="navbar navbar-template">
        <div class="row col-xs-12 text-center">
          <ul>
            <li class="active">
              <a href="#Home">Home</a>
            </li>
            <li>
              <a href="#AboutUs">AboutUs</a>
            </li>
            <li>
              <a href="#Images">Images</a>
            </li>
            <li>
              <a href="#Contact">Contact</a>
            </li>
          </ul>
        </div>
      </nav>

      <section class="scrollspy" id="Home">
      Home
      </section>

      <section class="scrollspy" id="AboutUs">
      AboutUs
      </section>

      <section class="scrollspy" id="Images">
      Images
      </section>

      <section class="scrollspy" id="Contact">
      Contact
      </section>
</body>
bnunamak
  • 524
  • 5
  • 15
  • Nice. Worked well. What is inefficient about it? – StevieD Oct 29 '18 at 01:15
  • I don't have any numbers, but for each scroll event call (which probably happens a multiple times per second when scrolling) you are iterating over every element, and then reapplying classes to each nav link. It should be fine since the number of elements / nav links is naturally bound by usability limitations, but it is a theoretically inefficient implementation :) – bnunamak Nov 01 '18 at 13:15
  • Yeah, I discovered the inefficiency. I made some big improvements. See my answer at https://stackoverflow.com/questions/53039757/optimizing-javascript-for-auto-scroll-feature – StevieD Nov 04 '18 at 16:32
  • Hey @bnunamak in chrome, when I click on any link, at that time of hovering the class constantly changes and the chrome hover effect also goes when scrolling. So styling also constantly changes as well. – Shashank Bhatt Oct 21 '19 at 19:12
8

To fix this, I wrote my own plugin. Which can be found here:

https://github.com/r3plica/Scrollspy

r3plica
  • 11,412
  • 17
  • 75
  • 203
  • bootstrap 4 alpha didn't have Scrollspy, so your plugin was good, but is there option to `refresh`, which updates current position ? – Shaiju T Mar 27 '17 at 14:42
  • This is awesome. Possible to change the active class to something else other than `active`? – Soolie Nov 21 '17 at 08:43
1

github.com/sxalexander/jquery-scrollspy doesn't seem to make <nav> menus active automatically as Bootstrap plug-in does.

However it does provide ID of the element that comes into view. See this JSFiddle that prints element IDs in the console.

You need to decide how to highlight menu item corresponding to the element having its ID. For example, set data-target="section1" attribute on menu link and then when element with ID section1 comes into view, locate the menu by $("#intel_nav a[data-target='" + "section1" + "']")

Gyrocode.com
  • 51,125
  • 13
  • 124
  • 164
1

You can use bootstrap's customize page to download ONLY scrollspy JS. You will also need the "nav" css. This link should be exactly what you need: http://getbootstrap.com/customize/?id=8f4a63b0157214af61c9ce380630a64d

Download the JS and CSS files and add them to your site. Scrollspy should work per bootstrap's docs (http://getbootstrap.com/javascript/#scrollspy)

Andrew
  • 21
  • 2
0

After reviewing all recommendations, I follow the Gyrocode.com idea, with the Mr. Sam Alexander (sxalexander) jquery-scrollspy, a nicely work based on David Walsh's MooTools scrollspy; I believe that is not to hard use this with any menu (with or without nav) or in any creative duty as the proposed by Gyrocode.com in their JSFiddle.

All my sections that can be reached when all have the same tag (as <section>) or in this case the same class name (.scrollspy), and the sections tell us their ID (as part of the plugin)

I share my implementation of this:

var menuSelected = null; // var to detect current selected element to pass the class that does visible the spy.

jQuery(document).ready(function( $ ){
  // Detect Initial scroll position
  var currentTop = $(window).scrollTop();

  $('.scrollspy').each(function (i) {
    var position = $(this).position();
    // Only to activate the top element ( current # ) 
    // if current is less than height.
    if ( i === 0 && !menuSelected && currentTop < $(this).height() ) navUpdate( $('a[href="#' + $(this).attr( 'id' ) + '"]') );

    // Basic implementation
    $(this).scrollspy({
      min: position.top - 100,
      max: position.top + $(this).height(),
      onEnter: function (element, position) {
        // update the button that have the element ID
        navUpdate( $('a[href="#' + element.id+ '"]') );
      }
    });
  });

  // method to update the navigation bar
  function navUpdate( where ){        
    if ( menuSelected ) menuSelected.removeClass( 'active' );
    menuSelected = where.parent();
    menuSelected.addClass( 'active' );
  }
});
jam65st
  • 57
  • 5