Jump to content
Shockowaffel

can scrollspy skip single navbar list items ?

Recommended Posts

Hi, I am no good with Javascript but I managed to copy paste my way to a working implementation of scrollspy to highlight my active navbar items.

So far so good

Now, the very first list item is the Home button and of course it gets highlighted when you are at the top of the page.
I would prefer if the home button would not be highlighted tough. I want a visually inactive navbar when I am at the top of the page.

Is there a script to do this or another way I am not seeing ?

<body data-spy="scroll" data-target=".navbar" data-offset="500">

<!-- Navbar (sit on top) -->
<nav class="navbar navbar-inverse navbar-fixed-top">
  <div class="container-fluid  ">
    <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>                        
     	</button>
     	<a class="navbar-brand brand w3-wide" href="#home">THORSTEN ERDT</a>
    </div>
    <div>
      <div class="collapse navbar-collapse" id="myNavbar">
        <ul class="nav navbar-nav">
          <li class="home w3-hide"><a href="#home"> HOME</a></li>
          <li><a href="#about"><i class="fa fa-user"></i> ABOUT</a></li>
          <li><a href="#portfolio"><i class="fa fa-th"></i> PORTFOLIO</a></li>
          <li><a href="#contact"><i class="fa fa-envelope"></i> CONTACT</a></li>
        </ul>
      </div>
    </div>
  </div>
</nav>    

 

Share this post


Link to post
Share on other sites

I don't know how scrollspy works, but if it uses classes or something to identify the item to highlight then use a different class so it doesn't find and highlight that item.  In general, find out how it highlights and avoid doing that for the one you don't want to highlight.

Share this post


Link to post
Share on other sites

That would be for the li items.

problem there is that putting a non li item inside a ul or in front of it would mess up the layout, wouldnt it ?

The navbar items are centered on the page right now.

Share this post


Link to post
Share on other sites

Usually JavaScript would add a class like 'active' to menu list item, to highlight a menu list-item that represents the current page. If you look through web developer tools (F12) at the li item in question, you should see an class that the others do not have. Then make note of the selector/s that make up the highlight of the list item or anchor, you can use an higher hierarchy id or class that will give it higher precedence over the current.

Share this post


Link to post
Share on other sites

So I THINK this is the JS part we need, but as I said, I am not good enough with JS to do anything with this really.

I assume the parts that mention ".nav li >  a" or "a" links in general are relevant.

}(jQuery),
+ function (t) {
  'use strict';
  function e(s, i) {
    this.$body = t(document.body),
    this.$scrollElement = t(t(s).is(document.body) ? window : s),
    this.options = t.extend({
    }, e.DEFAULTS, i),
    this.selector = (this.options.target || '') + ' .nav li > a',
    this.offsets = [
    ],
    this.targets = [
    ],
    this.activeTarget = null,
    this.scrollHeight = 0,
    this.$scrollElement.on('scroll.bs.scrollspy', t.proxy(this.process, this)),
    this.refresh(),
    this.process()
  }
  function s(s) {
    return this.each(function () {
      var i = t(this),
      n = i.data('bs.scrollspy'),
      a = 'object' == typeof s && s;
      n || i.data('bs.scrollspy', n = new e(this, a)),
      'string' == typeof s && n[s]()
    })
  }
  e.VERSION = '3.3.7',
  e.DEFAULTS = {
    offset: 10
  },
  e.prototype.getScrollHeight = function () {
    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  },
  e.prototype.refresh = function () {
    var e = this,
    s = 'offset',
    i = 0;
    this.offsets = [
    ],
    this.targets = [
    ],
    this.scrollHeight = this.getScrollHeight(),
    t.isWindow(this.$scrollElement[0]) || (s = 'position', i = this.$scrollElement.scrollTop()),
    this.$body.find(this.selector).map(function () {
      var e = t(this),
      n = e.data('target') || e.attr('href'),
      a = /^#./.test(n) && t(n);
      return a && a.length && a.is(':visible') && [
        [a[s]().top + i,
        n]
      ] || null
    }).sort(function (t, e) {
      return t[0] - e[0]
    }).each(function () {
      e.offsets.push(this[0]),
      e.targets.push(this[1])
    })
  },
  e.prototype.process = function () {
    var t,
    e = this.$scrollElement.scrollTop() + this.options.offset,
    s = this.getScrollHeight(),
    i = this.options.offset + s - this.$scrollElement.height(),
    n = this.offsets,
    a = this.targets,
    o = this.activeTarget;
    if (this.scrollHeight != s && this.refresh(), e >= i) return o != (t = a[a.length - 1]) && this.activate(t);
    if (o && e < n[0]) return this.activeTarget = null,
    this.clear();
    for (t = n.length; t--; ) o != a[t] && e >= n[t] && (void 0 === n[t + 1] || e < n[t + 1]) && this.activate(a[t])
  },
  e.prototype.activate = function (e) {
    this.activeTarget = e,
    this.clear();
    var s = this.selector + '[data-target="' + e + '"],' + this.selector + '[href="' + e + '"]',
    i = t(s).parents('li').addClass('active');
    i.parent('.dropdown-menu').length && (i = i.closest('li.dropdown').addClass('active')),
    i.trigger('activate.bs.scrollspy')
  },
  e.prototype.clear = function () {
    t(this.selector).parentsUntil(this.options.target, '.active').removeClass('active')
  };
  var i = t.fn.scrollspy;
  t.fn.scrollspy = s,
  t.fn.scrollspy.Constructor = e,
  t.fn.scrollspy.noConflict = function () {
    return t.fn.scrollspy = i,
    this
  },
  t(window).on('load.bs.scrollspy.data-api', function () {
    t('[data-spy="scroll"]').each(function () {
      var e = t(this);
      s.call(e, e.data())
    })
  })
}(jQuery);

 

Edited by Shockowaffel

Share this post


Link to post
Share on other sites

You don't have alter the js code, you just have to create CSS selector that will have a higher precedence than the CSS selector that targets the class the javascript code adds.

 

Share this post


Link to post
Share on other sites

I feel stupid, but I do not understand what you are suggesting.

I have an idea what you mean, but what I am trying isnt working.

sth like

#homebutton {background-color: transparent;}

or the same as an inline style isnt working either.

Edited by Shockowaffel

Share this post


Link to post
Share on other sites

Ah I get it! Thanks.

This actually does it

.nav li  a {background-color:transparent !important;
}

This works and overrides the js. Sadly (and as expected) it also overrides all other navbar item backgrounds. As mentioned before, I'd like to only override the home button.
Any idea on how to limit this effect to only one element instead of all ?

Share this post


Link to post
Share on other sites

Obviously, because you are targeting ALL anchor links, not just the specific anchor link that is highlighted because it is following a specific selector that includes the highlighting class included by JavaScript to highlight it in the first place.

Share this post


Link to post
Share on other sites

Thanks for the help, I finally figured it out !

.navbar-inverse .navbar-nav>.home>a {
	background-color: transparent !important;
	color:#9d9d9d !important;
	}
.navbar-inverse .navbar-nav>.home>a:hover {
	color:#fff !important;
	}

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×