Replacing navbar class based on screen size - javascript

Question
How can I swap classes of my navbar using javascript.
Background
I have a fixed navbar that I am trying to change to a static navbar on smaller screen sizes (< 768px) because my mobile menu pusher is having layout problems due to the fixed nav.
HTML
<nav class="navbar navbar-default navbar-fixed-top" id="mynav">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-
toggle="collapse" data-target="#navbar" aria-expanded="false" aria-
controls="navbar">
<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="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active">Home</li>
<li>About</li>
<li>Products</li>
<li>Contact</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
I tried creating a javascript function to add / remove the static nav class but for some reason it's not working.
JS
function changeNav() {
if ($(window).width() < 768) {
$("#mynav").addClass("navbar-static-top");
$("#mynav").removeClass("navbar-fixed-top");
} else {
$("#mynav").removeClass("navbar-static-top");
$("#mynav").addClass("navbar-fixed-top");
}
}
changeNav();

You can use this instead, this is propper and have better performances:
let lastState = false;
function checkForViewportChange () {
var state = window.matchMedia("(max-width: 768px)").matches;
if (state != lastState) {
if (state) {
//do your stuff here
} else {
//do your other stuff here
}
lastState = state
}}
window.setInterval (checkForViewportChange, 150);

You should check every time user resizes the screen, use .resize() method
Ex.
$(window).resize(() => {
let b = $(window).width() < 768;
$("#mynav").addClass("navbar-"+(b ? "static":"fixed")+"-top");
$("#mynav").removeClass("navbar-"+(b ? "fixed":"static")+"-top");
});

This is probably easier done with css media queries than javascript.
Example:
#media (max-width: 768px) {
// styles for device width <= 768px
}
If you really want to use javascript, then the answer from Abdeslem Charif is a good start

Related

($(window).scrollTop() > not working on IOS

I am using below JS code to fix header at the top for mobile only.
means if screen is scrolled for 80px css classes will be replaced.
working on android and PC but no luck on Ios.
any suggestions?
$(window).scroll(function () {
if ($(window).width() < 768) {
if ($(window).scrollTop() > 80) {
$('.navbar-right').addClass('custom-fixed-top');
}
else{
$('.navbar-right').removeClass('custom-fixed-top');
}
}
});
HTML CODE
<nav class="navbar navbar-default">
<div class="mid-container">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed hidden-xs" 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="#"><img src="images/logo.png" class="img-responsive" alt="logo"></a>
</div>
<div class="navbar-collapse collapse in" id="bs-example-navbar-collapse-1" aria-expanded="true" style="">
<ul class="nav navbar-nav navbar-right">
<li class="hidden-xs"><a class="hdr-orng-btn" href="#">受付時間</a></li>
<li class="hidden-xs"><a class="" href="#">10:00~19:00</a></li>
<li><a class="num" href="tel:03-0000-0000">TEL 03-0000-0000</a></li>
<li><a class="hdr-grn-btn" href="#contact_form">お問い合わせ</a></li>
</ul>
</div>
</div>
</div>
.navbar-nav.custom-fixed-top{
position: fixed;
top: 0;
width: 100%;
height: auto;
padding: 0 15px 15px;
margin: 0;
z-index: 2;
background-color:#fff;
left:0;
}
this is the code.
Ok this might seem far fetched but...
Try add the following to your CSS in your html tag if they're on IOS:
cursor: pointer;
Maybe can be your if verification of viewport screen width with 768, verify if you use some screen above that size.
I try replicate your code here, but $(window).scrollTop() works fancy here for me.
Image with your code on google chrome
Try changing this;
if ($(window).scrollTop() > 80) {...
To this;
if ($(body).scrollTop() > 80) {...
If that then works on ios, then that's the issue, so to cover both devices/browsers implement something like this;
var scrollentity = $('html,body');
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/))
{ scrollentity = $('body') }
else { scrollentity = $('html,body') }
scrollentity .scrollTop() > 80) {...
Hope it helps.

Getting navigation to display the selected page

I'm struggling with getting my navigation menu to show the selected page. I'm using the Bootstrap framework to build my site. This is my navigation menu:
<nav class="navbar">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<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="/index.html">Digital Transformation</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav pull-right">
<li class="active">Transformation deck</li>
<li>Background information</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
As far as I can tell, Bootstrap uses the following JS to make the selected menu item active, which I have in my header:
<script>
$('label').click(function() {
$(this).parent('li').toggleClass('active');
});
</script>
However with this code my primary nav item is active on page load, but when I select the second item it keeps 'Tranformation deck' as active instead of 'Background information'.
Am I missing a trick here? Any help would be greatly appreciated.
If you want to hook up click listeners to your nav items, your script should be something like this:
<script>
$('#navbar nav li a').click(function() {
$(this).parent('li').toggleClass('active');
});
</script>
You don't have any 'label' tags in your code, so there isn't anything to attach click event handlers to.
$(function() {
// this will get the full URL at the address bar
var url = window.location.href;
// passes on every "a" tag
$("#navbar a").each(function() {
// checks if its the same on the address bar
if (url == (this.href)) {
$(this).closest("li").addClass("active");
}
});
});

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();
}
});
}
}
});

Add brand logo and a li when navbar fixed top on scroll

<div class="container" id="menubar_1">
<nav class="navbar navbar-inverse" id="menubar_1">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#main_menu" 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="#"><img src="assets/images/logo.png" alt="logo" /></a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="main_menu">
<ul class="nav navbar-nav menu_bar text-uppercase">
<li class="active">adfadad</li>
<li>adfafaf</li>
<li>adadfa</li>
<li>ada</li>
<li class="contact_us">adfadfadf</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
</div>
normally navbar has in to container without barnd-logo and the li's last-child.i want the result when the navbar scroll to top container class will removed and navbar-brand, li's last child will be added in the navbar.
I will try this js given below .
var distance = $('#menubar_1').offset().top;
$(window).scroll(function () {
if ($(window).scrollTop() >= distance) {
$('#menubar_1').addClass("fixed_top");
$('#menubar_1').removeClass("container");
$('#menubar_1').addClass("navbar-brand");
$('#menubar_1').addClass("contact_us");
} else {
$('#menubar_1').removeClass("fixed_top");
$('#menubar_1').addClass("container");
$('#menubar_1').removeClass("navbar-brand");
$('#menubar_1').removeClass("contact_us");
}
});
then fixed-top css is here:
.fixed_top {
width: 100%;
height: 50px;
top: 0px;
position: fixed;
overflow: visible!important;
z-index: 9998;
background: #fff;
padding-top:15px;
padding-bottom: 15px;
}
please help me with the scripts
finally i got the answer
<script>
var distance = $('#menubar_1').offset().top;
$(window).scroll(function () {
if ($(window).scrollTop() >= distance) {
$('#menubar_1').addClass("navbar-fixed-top");
$('#menubar_1').removeClass("container");
$('.navbar-brand').css("float" , "none");
$('.navbar-brand').css("display" , "block");
$('.contact_us').css("display" , "block");
} else {
$('#menubar_1').removeClass("navbar-fixed-top");
$('#menubar_1').addClass("container");
$('.navbar-brand').css("display" , "none");
$('.contact_us').css("display" , "none");
}
});
</script>

How to add a class depending on screen dimensions with AngularJS

How can I add a class for an element, depending on the current screen dimensions?
Now I'm using Bootstrap's hidden-xs and visible-xs to handle it, but this requires duplicated code and elements in the DOM.
Update:
Overriding Bootstrap's predifined classes is not an option for me. Correct me if I'm wrong, but this would just be a hack and is bad practise in my point of view.
You can create directive for that purpose like below, but using CSS media queries seems to be better solution.
Please see here as well http://jsbin.com/mukec/1/edit?html,css,js,output
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
});
app.directive('top', function($window) {
return {
restrict: 'AE',
link: function(s, e, a) {
var body = angular.element(document.getElementsByTagName("body"));
$window.onresize = function(event) {
var clientWidth = document.documentElement.clientWidth;
if (clientWidth < 768)
{
e.removeClass('navbar-default')
e.addClass('navbar-fixed-top')
body.addClass('top50')
} else {
e.removeClass('navbar-fixed-top');
e.addClass('navbar-default');
body.removeClass('top50')
}
}
}
}
})
.navbar-fixed-top {
background-color: red
}
.navbar-default {
background-color: green
}
.top50 {
padding-top: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<body ng-app="app">
<div class="navbar" top>
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<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="#">Brand</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active">Home
</li>
<li>Link
</li>
<li>More
</li>
<li>Options
</li>
</ul>
</div>
</div>
<h1>SCROLL CONTENT</h1>
<img src="" height="1500px" />
</body>
May not be best practice but you could write a function that takes the screen size then applies the class
function screenLayout() {
var clientWidth = document.documentElement.clientWidth;
}
var classtoadd = angular.element('navbar');
if (clientWidth > 1024) {
classtoadd.addClass('largeScreen')
} else {
classtoadd.addClass('otherScreen')
}
Could just do it straight javascript or JQuery too

Categories