JQuery NavBar code causing scrolling to div issue - javascript

Question Background:
I have a standard bootstrap NavBar that collpases to a button on mobile devices.
The Issue:
When the user clicks on an item in the NavBar dropdown list the page will scroll down to the corrosponding div. I have a piece of JQuery that collpases the dropdown menu when the item has been clicks.
Without the JQuery to close the dropdown Nav menu the page scrolls down to the div with no issues. With the JQuery the page is scrolling down but stops well after the set 10px offset.
Without the JQuery menu closing code - working:
Note the small 10px above the panel item, this is what is wanted.
With the JQuery closing code - Broken:
Note that the page now scrolls down past the top of the div.
The Code:
The NavBar:
<div class="navbar">
<nav class="navbar navbar-default navbarColour" role="navigation" id="nav">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<img src="~/Images/DC.png" class="dc">
</div>
<div class="middleNavPadding">
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav pull-right">
<li>Services</li>
<li>Our Mission</li>
<li>Projects Gallery</li>
<li>Contact Us</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
The JQuery Menu closing code:
$(document).ready(function () {
$(".navbar-nav .scroll-link").click(function (event) {
$(".navbar-collapse").collapse('hide');
});
});
The JQuery used to scroll to the Div as set in the NavBar menu:
$(document).ready(function () {
$('.scroll-link').on('click', function (event) {
event.preventDefault();
var sectionID = $(this).attr("data-id");
scrollToID('#' + sectionID, 750);
});
function scrollToID(id, speed) {
var offSet = 10;
var targetOffset = $(id).offset().top - offSet;
$('html,body').animate({ scrollTop: targetOffset }, speed);
}
});
The HTML Markup of the Panel:
<div id="Info">
//panel HTML
</div>
I believe the issue is that the JQuery is setting the 'top' of the page as the bottom of the dropdown menu which is then causing a false offset. Any help with solving a a solution to this would be much appreciated.

You are on the right track, just add the height of the #bs-example-navbar-collapse-1 to your offset.
function scrollToID(id, speed) {
var offSet = 10 + $('#bs-example-navbar-collapse-1').height(); // NAVBAR HEIGHT !!!
var targetOffset = $(id).offset().top - offSet;
$('html,body').animate({ scrollTop: targetOffset }, speed);
}
This should work.

Related

Bootstrap navigation anchor goes further than expected and then snaps back, why?

So recently I have implemented smooth scroll given by CSS-Tricks, and a solution to closing the navigation bar when an option has been clicked. The problem is, that without the bootstrap script for closing the navigation, the scroll works perfect and stops at the anchors accurately.
However, as soon as I add the code for the automatic bootstrap navigation closing, when I then proceed to click on the link, it goes down to the desired anchor, misses it, continues and then suddenly shoots back to the anchor.
What could be the problem?
I hope someone will be able to help me. I have attached the relevant pieces of code below.
Smooth Scroll provided by CSS Tricks:
<script>
.click(function(event) {
// On-page links
if (
location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '')
&&
location.hostname == this.hostname
){
// Figure out element to scroll to
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
// Does a scroll target exist?
if (target.length) {
// Only prevent default if animation is actually gonna happen
event.preventDefault();
$('html, body').animate({
scrollTop: target.offset().top
}, 1000, function() {
// Callback after animation
// Must change focus!
var $target = $(target);
$target.focus();
if ($target.is(":focus")) { // Checking if the target was focused
return false;
} else {
$target.attr('tabindex','-1'); // Adding tabindex for elements not focusable
$target.focus(); // Set focus again
};
});
}
}
});
</script>
JavaScript code to close the bootstrap 3.x navigation:
<script>
$('.navbar-collapse a').click(function(){
$(".navbar-collapse").collapse('hide');
});
</script>
My HTML code:
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Navigation logo and dropdown icon -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#" id="logo">LOGO</a>
</div>
<!-- Navigation Options -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right" id="nav-appearance">
<li id="main-nav">Home <span class="sr-only">(current)</span></li>
<li id="main-nav">About Us</li>
<li id="main-nav">Services</li>
<li id="main-nav">Gallery</li>
<li>Contact</li>
</ul>
</div>
</div>
</nav>
not 100% certain but it looks like the scroll script triggers and calculates the position in the document to scroll to and animates that over time provided.
Meanwhile your nav gets collapsed and removed from the document flow, meaning the calculation of position is now off so when the animation completes it has overshot desired position.
The scroll script then calls a callback function which gives focus to the target element, but as it is off the page giving focus causes it to snap back up the page so the focussed element is visible.
If you can call the scroll script after the bootstrap collapse script this should resolve the issue.

Scrolltop animation not working

I am using this js to scroll to the id of the page. I took it from w3 schools and it works on my other site, so I don't understand why it doesn't work on my new site. It goes to the correct part of the page, but it doesn't do the scroll animation.
js:
<script>
$(document).ready(function () {
$(".navbar a, footer a[href='#myPage']").on('click', function (event) {
if (this.hash !== "") {
event.preventDefault();
var hash = this.hash;
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 900, function () {
window.location.hash = hash;
});
}
});
})
</script>
html navbar code:
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<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>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right">
<li>ABOUT</li>
<li>CLIENTS</li>
<li>SESSIONS</li>
<li>CONTACT</li>
</ul>
</div>
</div>
</nav>
Please let me know if you need to see any other code. Thanks!
That should work.
Are you positive that the new site is using jQuery and that the IDs of the element that you are scrolling to are correct?
Is your console displaying an error?

JQuery animation and slideUp delay issue

I am using a bootstrap navbar, and above the navigation links I have some text which I want to hide when the user scrolls down. Also, i want the navbar to be fixed top.
I am using a slideUp() and slideDown() to hide/show the text above the navbar, and I am using Jquery animate() to modify the navbar's height. (I need to have it's height explicit because of CSS reasons irrelevant to this issue)
The problem is that when I scroll to the top, the animate() gets queued after the slideDown() (Maybe it is not queued but it has some unwanted delay), which does not happen in the scrolling-down case. I want them to be simultaneous.
Here is a JSFiddle with minimal code reproducing the problem.
Here is the relevant minimal code:
html:
<nav class="navbar navbar-default navbar-fixed-top">
<div class="header">
AtenciĆ³n 24 horas 0800-777-8101
</div>
<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="brand" href="#"><img src="img/logo.jpg" class="logo" /></a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active">DSDSADSA</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>ADSASD</li>
</ul>
</div>
</div>
</nav>
<div style="height:1000px;background-color:#ccc;padding:50px;"></div>
css:
.navbar {
height: 110px;
}
div.header{
text-align:right;
height:50px;
}
And the most important, Javascript:
$(document).ready(function(){
$(window).scroll(function() {
if ($(document).scrollTop() > 0) {
console.log('a');
$('.navbar').animate({height: '60px'});
$('div.header').slideUp();
} else {
console.log('b');
$('.navbar').animate({height: '110px'});
$('div.header').slideDown();
}
});
});
Your problem is, everytime you scroll when the scrollTop is greater than 0 it is applying:-
$('.navbar').animate({height: '110px'});
$('div.header').slideDown();
and not just when its up, (height and slideUp). This causes the else to fire multiple times. see the console for a
One way of fixing this is applying a class to .header to determine if you need to apply the animation. like so:-
$(document).ready(function(){
$(window).scroll(function() {
if ($(document).scrollTop() > 0 && !$('div.header').hasClass('hide')) {
console.log('a');
$('.navbar').animate({height: '60px'}, "fast");
$('div.header').slideUp("fast").toggleClass('hide');
} else if ($(document).scrollTop() == 0 && $('div.header').hasClass('hide')) {
console.log('b');
$('.navbar').animate({height: '110px'}, "fast");
$('div.header').slideDown("fast").toggleClass('hide');
}
});
});
Fiddle
or you could use data or a variable, etc.
Before you apply the animation or slideup make use of stop function to clear the queue.
$('div.header').stop();
$('.navbar').stop();
Check out the working demo for you code here JSfiddle
Determining if your .navbar is currently in the state of animation will do the trick, based on which you can decide NOT to animate.
Just add the following snippet which uses jQuery's is() method, and returns false if the .navbar is in the animation state:
if($('.navbar').is(':animated')){
return false;
}
JSFiddle

How to make nav bar collapse only when in moble view

I am having issues with the nav bar collapsing when in full screen view. I want the nav bar to collapse in the hamburger via the mobile screen and i wrote a custom directive. Now when in full screen and you click a link the nav bar collapses and is causing an annoying flicker! Any ideas or help would be greatly appreciated!
Here is my code:
js:
.directive('collapseMenu', function () {
return {
link: function (scope, elem, attrs) {
$('.nav a').on('click', function(){
$('.navbar-toggle').click()
});
}
}
});
html:
<!-- Navigation -->
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div collapse-menu class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-1">
<span class="sr-only">Show Menu</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- navbar-brand is hidden on larger screens, but visible when the menu is collapsed -->
<a class="navbar-brand" href="#/home"></a><a <img src="images/phone.png" alt="press to call"></a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="navbar-collapse-1" >
<ul class="nav navbar-nav">
<li><a class="home" href="#/home">Home</a></li>
<li><a class="about" href="#/about">About</a></li>
<li><a class="con" href="#/contact">Contact</a></li>
<li><a class="review" href="#/review">Reviews</a></li>
<li><a class="admin" href="#/admin">Admin</a></li>
</ul>
</div>
</div>
</nav>
So, if you want to eliminate the collapse on larger screens, you'll have to add a screen width check to your link click function. And, if it's less than a certain size, you fire off the .navbar-toggle click function. Otherwise, you do nothing. You could check the screen width using $(window).width(). So, your directive code would become:
.directive('collapseMenu', function () {
return {
link: function (scope, elem, attrs) {
$('.nav a').on('click', function(){
if ($(window).width() <= 1200) {
$('.navbar-toggle').click();
}
});
}
}
});

bootstrap 3 customized fixed navigation on scroll with fade effect

I am trying to fade in the navigation bar and stick to top while scrolling to bottom of the page. Its fade effect works only the first time. My code is below.
<style type="text/css">
.navOpacity{
opacity: 0;
}
</style>
<script type="text/javascript">
$(document).ready(function(){
$(window).scroll(function(){
var ht = $('header').height()+70;
if($(this).scrollTop() >= ht){
$("#navb").addClass("navbar-fixed-top navOpacity")
.fadeTo('slow','1');
$(".row:first").css("padding-top","50px");
}else{
$("#navb").removeClass("navbar-fixed-top navOpacity");
$(".row:first").css("padding-top","0px");
}
});
});
</script>
<div class="container">
<header class="page-header">
<h1>Hello world</h1>
</header>
<nav id="navb" class="navbar navbar-default">
<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" href="#">WebSiteName</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li class="dropdown">
<a class="dropdown-toggle"
data-toggle="dropdown" href="#">Page 1
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>Page 1-1</li>
<li>Page 1-2</li>
<li>Page 1-3</li>
</ul>
</li>
<li>Page 2</li>
<li>Page 3</li>
</ul>
</div>
</nav>
<div class="row">
<div class="col-md-4">
<h3>h1. Bootstrap heading</h3>
Hello world and Mario.
</div>
<div class="col-md-4">
<h3>h2. Bootstrap heading</h3>
Hello world and Mario.
</div>
<div class="col-md-4">
<h3>h3. Bootstrap heading</h3>
Hello world and Mario.
<img src="rsz_myimg.jpg" class="img-responsive" />
</div>
</div><!-- end or row class-->
</div><!-- end container class-->
Your problem is that after the first time fadeTo is executed, your element is left with a style="opacity: 1" attribute, which is left there. So you have to remove it when you scroll to the top.
I've also changed the way the navbar is hidden, I suggest using .hide(), cause it also uses the elements' style attribute, that way it will not be overridden. And there's also a navbarVisible var that is used to determine if the navbar is already faded in and if it is, the code for fading it in is not executed when not needed. This should be a tiny step up in performance.
This seems to work just fine:
<script type="text/javascript">
$(document).ready(function(){
var navbarVisible = false;
$(window).scroll(function(){
var ht = $('header').height()+70;
if ($(this).scrollTop() >= ht) {
if (!navbarVisible) {
$("#navb").addClass("navbar-fixed-top")
.hide()
.fadeTo('slow','1');
$(".row:first").css("padding-top","50px");
navbarVisible = true;
};
} else {
$("#navb").removeClass("navbar-fixed-top").removeAttr('style');
$(".row:first").css("padding-top","0px");
navbarVisible = false;
}
});
});
</script>
You don't need this part anymore:
<style type="text/css">
.navOpacity{
opacity: 0;
}
</style>
Here's a link to an example JSFiddle with working code: JSFiddle Link
My two cents...
Just add this Javascript and away you go. Currently configured to graduate over the first 200px of scroll.
var scrollFadePixels = 200;
var fadeNavbar = function (window)
{
var opacity = window.scrollTop() / scrollFadePixels;
$('.navbar-fixed-top').css('background-color', 'rgba(34,34,34,' + opacity + ')');
}
fadeNavbar($(window));
$(window).scroll(function () {
fadeNavbar($(this));
});

Categories