javascript - Bootstrap Scrollspy causes issues with Off-Canavas Menu - Stack Overflow

UPDATE:To clear up some confusion I added a fiddle that demonstrates how it is supposed to work, but i

UPDATE: To clear up some confusion I added a fiddle that demonstrates how it is supposed to work, but it is just missing the scrollspy: / How can I add the scrollspyto this fiddle so that the menu highlights when I'm on a specific section?

I created a fixed left menu that turns into an off-canvas menu at <992px in browser width for tablet and mobile. When I select the anchor link on a browser width >992px it closes the menu and navigates to the anchor link section.

Custom JQuery Code: This is my custom jQuery code that closes the Off-Canvas Menu when I click on an anchor link:

// close off-canvas menu and navigate to anchor
$('.navmenu-nav li a').on('click', function() {
  $('body').removeClass('bs.offcanvas');
});

PROBLEM:

I decided to add a bootstrap offscrollspy and it works as intended after the browser width is greater than 992px, but when I resize the browser width to less than 992px this interferes with the Custom Jquery Code to close the menu and navigate to the anchor link.

Here's the Fiddle:

Bootstrap ScrollSpy causes issue with Off Canvas Menu and JQuery Code

My GUESS: I'm guessing the solution to this problem is to use jquery or javascript to prevent or remove the data-target=".navmenu" from activating when my screen is less than the <992px. Or we can find a way to only activate the scrollspy after >992px. I'm currently trying to figure this out, but I need someone who is a true expert in jquery to solve this dilemma.

Pre-Requisite:

  • Bootstrap.min.css
  • Bootstrap.min.js
  • jasny-bootstrap.css
  • jasny-bootstrap.js

JS:

$(document).ready(function () {
  toggleOffcanvas($(window).width() <= 992);
});

// simulate modal opening
$('.nav-link').click(function() {
  if ($(window).width() > 992) {
    $('.backdrop').hide(0, false);
  }

    $('#navToggle').click();
});

$('.navmenu').on('show.bs.offcanvas', function() {
    if ($(window).width() <= 992) {
        $('.backdrop').fadeIn();
  }
});

$('.navmenu').on('hide.bs.offcanvas', function() {
    if ($(window).width() <= 992) {
        $('.backdrop').fadeOut();
  }
});

// close modal on resize
$(window).resize(function() {
  if ($(window).width() > 992) {
    $('.backdrop').hide(0, false);
    $('body').removeClass('bs.offcanvas');
  }

  toggleOffcanvas($(window).width() <= 992);
});

// switch active navigation link onclick
$('.nav a').on('click', function() {
  $('.nav').find('.active').removeClass('active');
  $(this).parent().addClass('active');
});

// close modal when navigating to anchor
$('.navmenu-nav li a').on('click', function() {
  $('body').removeClass('bs.offcanvas');
});

function toggleOffcanvas(condition) {
    if (!! condition) {
    $('.nav-link').attr('data-toggle', 'offcanvas');
  } else {
    $('.nav-link').removeAttr('data-toggle');
  }
}

html:

<body data-spy="scroll" data-target="#myScrollspy" data-offset="50">


<div class="backdrop"></div>

<div id="myScrollspy" class="navmenu navmenu-default navmenu-fixed-left offcanvas-sm colornav ">
<a href="#" class="close" data-toggle="offcanvas" data-target=".navmenu">&times;</a>
 <a id="navToggle" class=""><span></span></a>
  <h4 class="navmenu-brand visible-md visible-lg visible-sm visible-xs" href="#">2017</h4>
  <ul class="nav navmenu-nav">
    <li class="active"><a class="nav-link" data-toggle="offcanvas" data-target=".navmenu" href="#january">Enero</a></li>
    <li><a class="nav-link" data-toggle="offcanvas" data-target=".navmenu" href="#february">Msrs</a></li>
    <li><a class="nav-link" href="/">Jupiter</a></li>
    <li><a class="nav-link" href="/">Off canvas navbar</a></li>
  </ul>

</div>

<div class="navbar navbar-default navbar-fixed-top navbar-preheader">
  <button type="button" class="navbar-toggle" data-toggle="offcanvas" data-target=".navmenu">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
  </button>
  <a class="navbar-brand" href="#">navbar brand</a>



</div>

<div class="container">
  <div class="page-header">
    <h1>Navmenu Template</h1>
  </div>
  <p class="lead">This example shows the navmenu element. If the viewport is <b>less than 992px</b> the menu will be placed the off canvas and will be shown with a slide in effect.</p>
  <p>Also take a look at the examples for a navmenu with <a href="">push effect</a> and <a href="">reveal effect</a>.</p>
  <p class="space"></p>
  <p id="january">January</p>
  <p id="february">February</p>
</div><!-- /.container -->
</body>

CSS:

html, body {
  height: 100%;
}
body {
  padding: 50px 0 0 0;
}
.space {padding-bottom:900px;}

.backdrop {
  background: rgba(0, 0, 0, 0.5);
  position: fixed;
  top: 0;
  bottom: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1040;
  display: none;
}

.navbar-fixed-top {

  background:#fff!important;
}


.navbar {
  display: block;
  text-align: center;
}
.navbar-brand {
  display: inline-block;
  float: none; 
}
.navbar-toggle {
  position: absolute;
  float: left; 
  margin-left: 15px;
}

.container {
  max-width: 100%;
}

@media (min-width: 1px) {
  .navbar-toggle {
    display: block !important; background:none!important;  border:none !important; color:#f90 !important;
  }
}

@media (min-width: 992px) {
  body {
    padding: 30px 0 0 300px;
  }
  .navmenu {
    padding-top: 0; 
  }

.navbar-toggle {display:none!important;}
.close {display:none}


.navmenu-fixed-left {
  z-index:0;
  top: 48px;
  bottom: 0; background:#fff!important;
}

}

    .navbar-default .navbar-toggle .icon-bar{
       background-color:#333;
    }


.close {margin-right:10px; margin-top:10px;}

@media (max-width:991px) {



.navmenu-fixed-left {
  z-index:1050;
  top: 0;
  bottom: 0; background:#fff!important;
}


}

    .backdrop {display:none}

    #january, #february {
      text-transform: uppercase;
      background-color: red;
      text-align: center;
      line-height: 90vh;
      font-size: 5em;
      height: 90vh;
      color: white;
    }

    #february {
      background-color: green;
    }

UPDATE: To clear up some confusion I added a fiddle that demonstrates how it is supposed to work, but it is just missing the scrollspy: https://jsfiddle/kmdLg7t0/ How can I add the scrollspyto this fiddle so that the menu highlights when I'm on a specific section?

I created a fixed left menu that turns into an off-canvas menu at <992px in browser width for tablet and mobile. When I select the anchor link on a browser width >992px it closes the menu and navigates to the anchor link section.

Custom JQuery Code: This is my custom jQuery code that closes the Off-Canvas Menu when I click on an anchor link:

// close off-canvas menu and navigate to anchor
$('.navmenu-nav li a').on('click', function() {
  $('body').removeClass('bs.offcanvas');
});

PROBLEM:

I decided to add a bootstrap offscrollspy and it works as intended after the browser width is greater than 992px, but when I resize the browser width to less than 992px this interferes with the Custom Jquery Code to close the menu and navigate to the anchor link.

Here's the Fiddle:

Bootstrap ScrollSpy causes issue with Off Canvas Menu and JQuery Code

My GUESS: I'm guessing the solution to this problem is to use jquery or javascript to prevent or remove the data-target=".navmenu" from activating when my screen is less than the <992px. Or we can find a way to only activate the scrollspy after >992px. I'm currently trying to figure this out, but I need someone who is a true expert in jquery to solve this dilemma.

Pre-Requisite:

  • Bootstrap.min.css
  • Bootstrap.min.js
  • jasny-bootstrap.css
  • jasny-bootstrap.js

JS:

$(document).ready(function () {
  toggleOffcanvas($(window).width() <= 992);
});

// simulate modal opening
$('.nav-link').click(function() {
  if ($(window).width() > 992) {
    $('.backdrop').hide(0, false);
  }

    $('#navToggle').click();
});

$('.navmenu').on('show.bs.offcanvas', function() {
    if ($(window).width() <= 992) {
        $('.backdrop').fadeIn();
  }
});

$('.navmenu').on('hide.bs.offcanvas', function() {
    if ($(window).width() <= 992) {
        $('.backdrop').fadeOut();
  }
});

// close modal on resize
$(window).resize(function() {
  if ($(window).width() > 992) {
    $('.backdrop').hide(0, false);
    $('body').removeClass('bs.offcanvas');
  }

  toggleOffcanvas($(window).width() <= 992);
});

// switch active navigation link onclick
$('.nav a').on('click', function() {
  $('.nav').find('.active').removeClass('active');
  $(this).parent().addClass('active');
});

// close modal when navigating to anchor
$('.navmenu-nav li a').on('click', function() {
  $('body').removeClass('bs.offcanvas');
});

function toggleOffcanvas(condition) {
    if (!! condition) {
    $('.nav-link').attr('data-toggle', 'offcanvas');
  } else {
    $('.nav-link').removeAttr('data-toggle');
  }
}

html:

<body data-spy="scroll" data-target="#myScrollspy" data-offset="50">


<div class="backdrop"></div>

<div id="myScrollspy" class="navmenu navmenu-default navmenu-fixed-left offcanvas-sm colornav ">
<a href="#" class="close" data-toggle="offcanvas" data-target=".navmenu">&times;</a>
 <a id="navToggle" class=""><span></span></a>
  <h4 class="navmenu-brand visible-md visible-lg visible-sm visible-xs" href="#">2017</h4>
  <ul class="nav navmenu-nav">
    <li class="active"><a class="nav-link" data-toggle="offcanvas" data-target=".navmenu" href="#january">Enero</a></li>
    <li><a class="nav-link" data-toggle="offcanvas" data-target=".navmenu" href="#february">Msrs</a></li>
    <li><a class="nav-link" href="http://www.jasny/bootstrap/examples/navmenu-reveal/">Jupiter</a></li>
    <li><a class="nav-link" href="http://www.jasny/bootstrap/examples/navbar-offcanvas/">Off canvas navbar</a></li>
  </ul>

</div>

<div class="navbar navbar-default navbar-fixed-top navbar-preheader">
  <button type="button" class="navbar-toggle" data-toggle="offcanvas" data-target=".navmenu">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
  </button>
  <a class="navbar-brand" href="#">navbar brand</a>



</div>

<div class="container">
  <div class="page-header">
    <h1>Navmenu Template</h1>
  </div>
  <p class="lead">This example shows the navmenu element. If the viewport is <b>less than 992px</b> the menu will be placed the off canvas and will be shown with a slide in effect.</p>
  <p>Also take a look at the examples for a navmenu with <a href="http://www.jasny/bootstrap/examples/navmenu-push">push effect</a> and <a href="http://www.jasny/bootstrap/examples/navmenu-reveal">reveal effect</a>.</p>
  <p class="space"></p>
  <p id="january">January</p>
  <p id="february">February</p>
</div><!-- /.container -->
</body>

CSS:

html, body {
  height: 100%;
}
body {
  padding: 50px 0 0 0;
}
.space {padding-bottom:900px;}

.backdrop {
  background: rgba(0, 0, 0, 0.5);
  position: fixed;
  top: 0;
  bottom: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1040;
  display: none;
}

.navbar-fixed-top {

  background:#fff!important;
}


.navbar {
  display: block;
  text-align: center;
}
.navbar-brand {
  display: inline-block;
  float: none; 
}
.navbar-toggle {
  position: absolute;
  float: left; 
  margin-left: 15px;
}

.container {
  max-width: 100%;
}

@media (min-width: 1px) {
  .navbar-toggle {
    display: block !important; background:none!important;  border:none !important; color:#f90 !important;
  }
}

@media (min-width: 992px) {
  body {
    padding: 30px 0 0 300px;
  }
  .navmenu {
    padding-top: 0; 
  }

.navbar-toggle {display:none!important;}
.close {display:none}


.navmenu-fixed-left {
  z-index:0;
  top: 48px;
  bottom: 0; background:#fff!important;
}

}

    .navbar-default .navbar-toggle .icon-bar{
       background-color:#333;
    }


.close {margin-right:10px; margin-top:10px;}

@media (max-width:991px) {



.navmenu-fixed-left {
  z-index:1050;
  top: 0;
  bottom: 0; background:#fff!important;
}


}

    .backdrop {display:none}

    #january, #february {
      text-transform: uppercase;
      background-color: red;
      text-align: center;
      line-height: 90vh;
      font-size: 5em;
      height: 90vh;
      color: white;
    }

    #february {
      background-color: green;
    }
Share Improve this question edited Feb 6, 2017 at 20:52 ChosenJuan asked Feb 2, 2017 at 14:36 ChosenJuanChosenJuan 9614 gold badges26 silver badges61 bronze badges 2
  • 2 I don't fully understand what the problem is and what you're trying to do. Can you boil it down a little bit? – Serg Chernata Commented Feb 5, 2017 at 13:28
  • I'm trying to make the bootstrap scroll spy activate when the browser width is 992px or greater, but when you reduce the screen size to 991px width or less the bootstrap scroll-spy should be removed or it will in cause issues with my off-canvas menu. – ChosenJuan Commented Feb 6, 2017 at 16:53
Add a ment  | 

3 Answers 3

Reset to default 1

The problem with the code is that data-target=".navmenu" on menu items breaks the scrollspy plugin. Basically, scrollspy makes the connection between menu item and an element on the page via either data-target property or href property. Here is a part of it's source code:

return `${selector}[data-target="${target}"],` +
       `${selector}[href="${target}"]`

Because of this you can't use data-target on menu links to close the menu. You can use javascript to close the menu instead.

Here is updated link's HTML:

<li class="active"><a class="nav-link" href="#january">Enero</a></li>
<li><a class="nav-link" href="#february">Msrs</a></li>

And all the javascript you need:

$(document).ready(function () {
  // Add the backdrop when menu is shown
  $('.navmenu').on('show.bs.offcanvas', function() {
    $('.backdrop').fadeIn();
  });

  // Remove the backdrop when menu is hidden
  $('.navmenu').on('hide.bs.offcanvas', function() {
    $('.backdrop').fadeOut();
  });

  // Hide the menu on menu item click
  $('.nav-link').click(function() {
    if ($(window).width() <= 992) {
      $('.navmenu').offcanvas('toggle');
    }
  });

  // Remove the backdrop if window is resized over the breakpoint
  $(window).resize(function () {
    if ($(window).width() > 992) {
      $('.backdrop').fadeOut();
    }
  });
});

A plete working example:

https://jsfiddle/kmdLg7t0/5/

Finally you have to remove all href="#" from link elements where they are not necessary. For example close menu button will take you back to # even if you have navigated to #january.

So things I did in total:

  • removed data- attributes from links
  • closing menu with javascript on link click
  • removed unnecessary href=# from links

Everything else is handled by plugins themselves.

By tying the scroll spy to a class, you can then toggle said class as needed. In addition, make sure to run the function once on page load to set initial state.

$('body').scrollspy({ target: '.scroll-spy' });

toggleScrollSpy($(window).width() <= 992);

// close modal on resize
$(window).resize(function() {
  if ($(window).width() > 992) {
    $('.backdrop').hide(0, false);
    $('body').removeClass('bs.offcanvas');
  }

  toggleScrollSpy($(window).width() <= 992);
});

function toggleScrollSpy(condition) {
  if (!!condition) {
    $('#myScrollspy').addClass('scroll-spy');
  } else {
    $('#myScrollspy').removeClass('scroll-spy');
  }
}

I would simply say when you animate or resize web page, make sure your coordinates top, left and height, width are carefully calculated. Because if they there is any change during resize it will show undesired positions. So its always good idea to examine coordinates and then alter dynamically them as the need arises.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745186287a4615654.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信