How can I hide nav bar when on top of page - javascript

Can anyone help me out with a small responsive web project I'm currently doing?
I want to hide the menu nav bar when the user is on the top most part of the page, and only show it when the user starts scrolling down (on the mobile version), but have no idea how to, below are my code segments (mostly based on W3school template as I'm trying to learn web page making and it is the most reliable source I've found so far):
<!-- Navbar -->
<div class="w3-top">
<ul class="w3-navbar w3-sea-green w3-card-2 w3-left-align">
<li class="w3-hide-medium w3-hide-large w3-opennav w3-right">
<a class="w3-padding-large" href="javascript:void(0)" onclick="myFunction()" title="Toggle Navigation Menu"><i class="fa fa-bars"></i></a>
</li>
<li>HOME</li>
<li class="w3-hide-small">DOWNLOAD</li>
<li class="w3-hide-small">ABOUT</li>
<li class="w3-hide-small">CONTACT</li>
</ul>
</div>
<!-- Navbar on small screens -->
<div id="navDemo" class="w3-hide w3-hide-large w3-hide-medium w3-top" style="margin-top:46px">
<ul class="w3-navbar w3-left-align w3-sea-green">
<li><a class="w3-padding-large w3-hover-text-sea-green-invert" href="#download">DOWNLOAD</a></li>
<li><a class="w3-padding-large w3-hover-text-sea-green-invert" href="#about">ABOUT</a></li>
<li><a class="w3-padding-large w3-hover-text-sea-green-invert" href="#contact">CONTACT</a></li>
</ul>
</div>
<script>
// Used to toggle the menu on small screens when clicking on the menu button
function myFunction() {
var x = document.getElementById("navDemo");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
} else {
x.className = x.className.replace(" w3-show", "");
}
}
// When the user clicks anywhere outside of the modal, close it
var modal = document.getElementById('ticketModal');
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
<!--Header image-->
<div class="mySlides w3-display-container w3-center">
<img src="pics/header_img.png" style="width:100%; pointer-events:none;" draggable="false">
</div>
Am really appreciating any help, many thanks!

Always use:
.classList.add() // To add the class
.classList.remove() // To remove the class
This makes your code:
function myFunction() {
var x = document.getElementById("navDemo");
if (x.className.indexOf("w3-show") == -1) {
x.classList.add("w3-show");
} else {
x.classList.remove("w3-show");
}
}
And finally, please don't follow W3Schools and you end up like this.

function change(){
navbar=document.getElementsByClassName("w3-top")[0];
if(window.scrollTop>20){
//show
navbar.style.display="block";
}else{
//hide
navbar.style.display="none";
}}
window.onload=window.onscroll=change;
On page load or if the user scroll, check if the user scrolled down...

you have to detect when the user scroll or not and if not scroll add class hidden and if scroll remove class hidden.
$(window).scroll(function (){
var scroll = $(window).scrollTop();
if (scroll >=20) {
$('.w3-top').removeClass('hidden');
}
else {
$('.w3-top').addClass('hidden');
}
});
the css
.hidden {
display: none;
}

Related

Changing menu options is NOT changing the active class even though I followed the solution in the link below

So, the website I'm working on is: http://wtr2022.webparity.net/. The link for the example is below.
How to change active class while click to another link in bootstrap use jquery?
So, I'll show the code I'm using and wrote and where to find it in the JS file.
HTML:
The below starts on line 77 when you open the DEBUG console or scroll to the tag.
<nav class="navbar navbar-expand-lg navbar-dark ftco_navbar bg-dark ftco-navbar-light sticky-top" id="ftco-navbar">
<div class="container">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#ftco-nav" aria-controls="ftco-nav" aria-expanded="false" aria-label="Toggle navigation">
<span class="fa fa-bars"></span> Menu
</button>
<div class="collapse navbar-collapse" id="ftco-nav">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">Home</li>
<li class="nav-item">About</li>
<li class="nav-item">Services</li>
<li class="nav-item">Project</li>
<li class="nav-item">Blog</li>
<li class="nav-item">Roofing</li>
<li class="nav-item">Contact</li>
</ul>
<div class="d-flex align-items-center justify-content-center">
<img src="images/logos/weathertight-logo.png" class="logosmaller" alt=""/>
<!-- <span class="flaticon-roof-2"></span> -->
</div>
<div class="col-3 d-flex justify-content-end align-items-center">
<div class="social-media">
<p class="mb-0 d-flex">
<span class="fa fa-facebook"><i class="sr-only">Facebook</i></span>
<span class="fa fa-twitter"><i class="sr-only">Twitter</i></span>
<span class="fa fa-instagram"><i class="sr-only">Instagram</i></span>
<span class="fa fa-dribbble"><i class="sr-only">Dribbble</i></span>
</p>
</div>
</div>
</div>
</div>
</nav>
<!-- END nav -->
JS:
The below starts on line: 194 or scroll until you find this code.
$('.navbar-nav li a').click((e) => {
$('.active').removeClass('active');
console.log("Argument for CLICK FUNCTION: ", e.currentTarget.innerHTML);
console.log("CURRENT TARGET for CLICK FUNCTION: ", e.currentTarget.parentElement);
if (e.currentTarget.innerHTML === "Services") {
funcs.changeAboutImage('sprayfoam');
}
// add the active class to the link we clicked
// console.log("THIS: ", $(this));
$(this).addClass('active');
// e.preventDefault();
});
/* Code for changing active link on clicking */
let btns = $("#ftco-nav .navbar-nav .nav-link");
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener("click",
() => {
let current = document.getElementsByClassName("active");
console.log("CURRENT: ", current);
// current[0].className = current[0].className.replace(" active", "");
// this.className += " active";
});
}
/* Code for changing active
link on Scrolling */
$(window).scroll(() => {
let distance = $(window).scrollTop();
// console.log($(window).scrollTop());
if ($(window).scrollTop() > 701) {
$('#ftco-navbar').addClass('navbar-fixed');
}
if ($(window).scrollTop() < 700) {
$('#ftco-navbar').removeClass('navbar-fixed');
}
$('.ftco-section').each(function (i) {
if ($(this).position().top <= distance + 250) {
$('.navbar-nav a.active').removeClass('active');
$('.navbar-nav a').eq(i).addClass('active');
}
});
}).scroll();
Here's what happens:
FIRST:
When I click on the FIRST SLIDE, "Learn more..." button, it needs to scroll to the GET A QUOTE section so the YELLOW bar with the words, GET A QUOTE appear. It's not.
SECOND:
If you start from the base URL http://wtr2022.webparity.net/ and SCROLL until the menu appears, you'll see HOME as active. BUT, when you click on About, or any other menu, the active menu fails to become highlighted.
THIRD
When you start at the base URL and SCROLL to "Roofing Services We Offer", below, you'll see SPRAY FOAM ROOFING already active, BUT, whenever you click on a menu, the ACTIVE spray foam menu and content is not active and nothing is there UNLESS you click on it.
This is what happens when you CLICK on a menu and scroll to Roofing Services We offer:
I think that the ACTIVE menu is TIED together, meaning, when the addEventListener() is hit, it REMOVES ALL active classes from everything, hence, the reason.
If anyone can assist me, I'd appreciate it. Thank you.
Your click handler on the <a> tags is adding/removing the .active class to the <a> tag but it should be doing it to the parent <li> tag:
$('#ftco-nav .navbar-nav li a').click((e) => {
$('#ftco-nav .active').removeClass('active');
$(e).parent().addClass('active');
// ...
}
Your scroll handler has a similar problem. It should be adding/removing the .active class from the <li class="nav-item"> tags, not the <a> tags:
if ($(this).position().top <= distance + 250) {
$('#ftco-nav .navbar-nav .nav-item.active').removeClass('active');
$('#ftco-nav .navbar-nav a').eq(i).parent().addClass('active');
}

Hide Collapse Menu & Toggle Menu in Angular

I found a problem, how do I do that when the user clicks on one of the dropdown menus on the mobile, it will close the previous dropdown menu and open the clicked menu? Then when the user click a menu inside the dropdown, it will close all dropdown menus including the toggle menu?
Here's the code I have
ngOnInit(): void {
if ($(window).width() < 991.98) {
document.querySelectorAll('.nav-item').forEach(function(element){
element.addEventListener('click', function (this: any, e) {
let nextEl = this.nextElementSibling;
if(nextEl && nextEl.classList.contains('dropdown-menu')) {
e.preventDefault();
if(nextEl.style.display == 'block'){
nextEl.style.display = 'none';
nextEl.style.opacity = '0';
nextEl.style.position = 'relative';
$(this).closest('li').removeClass('active');
} else {
nextEl.style.display = 'block';
nextEl.style.opacity = '1';
nextEl.style.position = 'relative';
$(this).closest('li').addClass('active');
}
}
});
})
}
}
collapse() {
this.showMenu = !this.showMenu;
var toggle;
if (this.showMenu == true) {
toggle = this.elRef.nativeElement.querySelector('.toggle-menu');
toggle.classList.add('active');
$('.header-area .nav').slideToggle(200);
} else {
toggle = this.elRef.nativeElement.querySelector('.toggle-menu');
toggle.classList.remove('active');
$('.header-area .nav').slideToggle(200);
}
}
index.html
<ul class="nav">
<li>
<a class="nav-item">Home</a>
<div class="dropdown-menu">
<a routerLink="/home" class="dropdown-item">Home</a>
<a routerLink="/dashboard" class="dropdown-item">Dashboard</a>
<a routerLink="/setting" class="dropdown-item">Setting</a>
</div>
</li>
<li>
<a class="nav-item">Explore</a>
<div class="dropdown-menu">
<a routerLink="/user" class="dropdown-item">User</a>
<a routerLink="/admin" class="dropdown-item">Admin</a>
</div>
</li>
</ul>
<a class="toggle-menu" (click)="collapse()">
<span>Menu</span>
</a>
First, I would say that you should not using JQuery and some basic Javascript document query syntaxs in Angular. Angular is not working like this.
Second, about the dropdown, thinking more simple, you need to determine which button was pressed, add class "active" if it not already there, and remove from all remaining

Can't target two different dropdowns properly by jQuery

I have two seperate dropdowns, whose hover states can't be target by css based on the html markup. I tried to solve this by jQuery and I am halfway done. One problem still exists all the time and I am trying to solve this by days now.
If I hover the link of the second dropdown and moves the mouse really fast to the link of the first dropdown and then move the mouse immediately into the container of the displayed first dropdown, this dropdown menu disappears. It seems that my script removes the adding css classes in this case. This situation only appears with fast mouse movement but it drives me crazy. I am unable to figure out why this happens. I include a jsfiddle demo, where you can see the problem by yourself.
jQuery
jQuery(document).ready(function($) {
var $body = $('body'),
$tg_header = $('#main-header'),
$tg_top_menu = $('ul.nav'),
/*$tg_submenu_link = $('.tg-submenu__link'),*/
$tg_submenu_link_tg = $('.tg-submenu__link--tg'),
$tg_submenu_link_abteilungen = $('.tg-submenu__link--abteilungen'),
$tg_submenu = $('.tg-submenu'),
$tg_submenu_tg = $('.tg-submenu__tg'),
$tg_submenu_abteilungen = $('.tg-submenu__abteilungen'),
et_menu_hover_triggered = false;
/* General Hiding Function for first mega menu */
function tg_hide_tg() {
setTimeout( function () {
if ($tg_top_menu.find('.tg-submenu__link--tg:hover').length == 0 && $('.tg-submenu__tg:hover').length == 0) {
$body.removeClass('tg-submenu__tg--active')
};
}, 50);
}
/* General Hiding Function for second mega menu */
function tg_hide_abteilungen() {
setTimeout( function () {
if ($tg_top_menu.find('.tg-submenu__link--abteilungen:hover').length == 0 && $('.tg-submenu__abteilungen:hover').length == 0) {
$body.removeClass('tg-submenu__abteilungen--active')
};
}, 50);
}
/* Mouse Hover Mega Link 1 and Leave Link */
$tg_submenu_link_tg.mouseenter(function() {
$body.addClass('tg-submenu__tg--active');
}).mouseleave(function() {
tg_hide_tg();
});
/* Mouse Leave Mega Menu Container 1 */
$tg_submenu_tg.mouseleave(function () {
setTimeout(function () {
if ($('.tg-submenu__link--tg:hover').length == 0 && $('.tg-submenu__tg:hover').length == 0 ) {
$body.removeClass('tg-submenu__tg--active');
};
},50)
});
/* Mouse Hover Mega Link 2 and Leave Link */
$tg_submenu_link_abteilungen.mouseenter(function() {
$body.addClass('tg-submenu__abteilungen--active');
}).mouseleave(function() {
tg_hide_abteilungen();
})
/* Mouse Leave Mega Menu Container 2 */
$tg_submenu_abteilungen.mouseleave(function () {
setTimeout(function () {
if ($('.tg-submenu__link--abteilungen:hover').length == 0 && $('.tg-submenu__abteilungen:hover').length == 0 ) {
$body.removeClass('tg-submenu__abteilungen--active');
};
},50)
});
});
HTML-Markup
<body>
<header id="main-header">
<div class="container">
<div id="et-top-navigation">
<div class="tg-mainMenu__left">
<nav id="top-menu-nav">
<ul id="top-menu" class="nav">
<li id="menu-item-154" class="tg-submenu__link tg-submenu__link--tg menu-item">MEGA LINK 1</li>
<li id="menu-item-156" class="tg-submenu__link tg-submenu__link--abteilungen menu-item">MEGA LINK 2</li>
<li id="menu-item-166" class="menu-item menu-item">Normal Link 3</li>
</ul>
</nav>
</div><!-- TG-mainMenu__left-->
<div class="tg-mainMenu__right">
<nav id="top-menu-nav">
<ul id="top-menu" class="nav">
<li id="menu-item-154" class="menu-item menu-item">Normal Link 4</li>
<li id="menu-item-154" class="menu-item menu-item">Normal Link 5</li>
<li id="menu-item-154" class="menu-item menu-item">Normal Link 6</li>
</ul>
</nav>
</div> <!-- tg-mainMenu__right -->
</div> <!-- #et-top-navigation -->
<!-- TG Mega 1 -->
<div class="tg-submenu tg-submenu__tg">
<div class="container tg-submenu__content">
<h1>
MEGA MENU 1
</h1>
</div>
</div>
<!-- Abteilungen Mega -->
<div class="tg-submenu tg-submenu__abteilungen">
<div class="container tg-submenu__content">
<h1>
MEGA MENU 2
</h1>
</div>
</div>
</div> <!-- .container -->
</header>
</body>
My fiddle: https://jsfiddle.net/hfammzce/
I dont know why this is happening. But you can use jQuery .show() and .hide() instead of using add/remove class and opacity.
Here is the updated fiddle: https://jsfiddle.net/1dzyszdq/
/* General Hiding Function for first mega menu */
function tg_hide_tg() {
setTimeout( function () {
if ($tg_top_menu.find('.tg-submenu__link--tg:hover').length == 0 && $('.tg-submenu__tg:hover').length == 0) {
$(".tg-submenu__tg").hide();
};
}, 50);
}
/* Mouse Hover Mega Link 1 and Leave Link */
$tg_submenu_link_tg.mouseenter(function() {
$('.tg-submenu__tg').show();
}).mouseleave(function() {
tg_hide_tg();
});

Show last active div on refresh JS

I have a fairly basic navigation tab on a single-page website that shows/hides divs. However, when I refresh the page, it goes back to the landing "page" div instead of staying on the current tab. I am using the following JS to switch between tabs and I would like to keep using this method if possible:
var links = document.getElementById('navs').getElementsByTagName('a');
for(var i = 0, link; link = links[i]; i++) {
link.onclick = showContent;
// Hide content divs by default
var contentdiv = getContentDiv(link)
if (contentdiv == null){
continue;
}
contentdiv.style.display = 'none';
}
// Show the first content div
if(links.length > 0) showContent.apply(links[0]);
var current;
function showContent() {
// hide old content
if(current) current.style.display = 'none';
current = getContentDiv(this);
if(!current) return true;
current.style.display = 'inline-block';
return true;
}
function getContentDiv(link) {
var linkTo = link.getAttribute('href');
console.log(linkTo);
// Make sure the link is meant to go to a div
if(linkTo.substring(0, 2) != '#!') return;
linkTo = linkTo.substring(2);
return document.getElementById(linkTo);
}
I know it refreshes to the landing div because of
if(links.length > 0) showContent.apply(links[0]);
However, I was hoping to use this method and store the link iteration number in a variable called current_link and then be able to call if(links.length > 0) showContent.apply(links[current_link]); or even if(links.length > 0) showContent.apply(current_link);
I have tried a couple ways, but it ends up just saving either the first or last tab in the navigation bar. Also the page refreshes to the default div, but the url stays the same. EX. The URL is http://example.com/#!tab1 even though the page is displaying http://example.com/#!home
This is the html:
<nav class="navbar navbar-fixed-top" id= "navs" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<div class="navbar-brand">
<a id="logo" href="#!home"><img id="logo-pic" src="images/name.png" alt="" width="50%" height="auto"></a>
</div>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="navbar" id="navbar-collapse-1">
<ul class="nav navbar-right navbar-nav">
<li class="dropdown">
tab1
</li>
<li>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">tab2</a>
<ul class="dropdown-menu dropdown-menu-right pull-center">
<li>tab21</li>
<li>tab22</li>
</ul>
</li>
<li>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">tab3</a>
<ul class="dropdown-menu dropdown-menu-right pull-center">
<li>resume</li>
<li>tab31</li>
<li>tab32</li>
</ul>
</li>
<li>
tab4
</li>
<li>
tab5
</li>
</ul>
</div>
</div>
<!-- /.container -->
</nav>
The best way to persist page state is to leverage the url history.
E.g. when the user clicks on a tab, instead of just doing the navigation:
Create a hashchange event handler
window.onhashchange = () => { ... };
or:
window.addEventListener('hashchange', () => ...);
So you might do something like:
const navigate = () => open_tab(location.hash.substr(1)); // get rid of the '#'
window.addEventListener('hashchange', navigate);
You also want to navigate when the page loads:
navigate();
Now, when the user clicks a tab, or whatever, change the hash of the page location:
location.hash = "tab1";
This is a little extra work but the benefits are huge:
Refreshing the page works as expected
If the user bookmarks the page, they bookmark the state of the UI
Forward and backward navigation now work as expected.

Modifying a JS Show/Hide to auto-show depending on page

I have a Javascript Show/Hide navigation bar on the website I'm currently working on that displays a sub navigation onclick. However, I would like the hidden subnavigation to automatically be displayed when the user is within that section of the site.
This is my JS:
<script type="text/javascript"><!--
function HideContent(d) {
document.getElementById(d).style.display = "none";
}
function ShowContent(d) {
document.getElementById(d).style.display = "block";
}
function ReverseDisplay(d) {
if(document.getElementById(d).style.display == "none") { document.getElementById(d).style.display = "block"; }
else { document.getElementById(d).style.display = "none"; }
}
//--></script>
And this is an example of the HTML:
<nav class="sub-nav" id="company-nav" style="display: none;">
<div class="container">
<ul>
<li>About</li>
<li>History</li>
<li>People</li>
</ul>
<img src="/2013/img/blue-nav-arrow.png" border="0" alt="arrow" />
</div>
</nav>
This works fine from the homepage - where all subnavs are hidden by default - but, for example, if a user goes into the About page I want the company-nav sub-nav to be displayed by default.
I don't know if a JS or CSS will achieve this and I'm a bit rusty, so I'll appreciate any suggestions. Thanks.
what you can do is for individual pages have an id for the body tag, and through CSS, if the id is active, display the submenu.
Eg (about page):
HTML:
<body id='about'>
<nav id"company-nav">
<li>About</li>
<li>History</li>
<li>People</li>
</nav>
</body>
CSS:
#about nav#company-id{
display:block;
}
Hope this helps.

Categories