active class is removed when page refreshes jQuery - javascript

I have a UL on my page which is acting as navigation. In my footer I have some jQuery code so when I click the link it removes the active class on the li and then places it on the current li that has been clicked. This works as I click however when the page reloads the active class goes back onto the previous li.
Here is my code
jQuery(document).ready(function () {
"use strict";
// Init Demo JS
Demo.init();
// Init Theme Core
Core.init();
$('.sidebar-menu > li').click(function (e) {
$(".active").removeClass("active");
$(this).addClass("active");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav sidebar-menu">
<li class="sidebar-label pt20">Menu</li>
<li class="active">
<a href="/dashboard">
<span class="glyphicon glyphicon-home"></span>
<span class="sidebar-title">Dashboard</span>
</a>
</li>
<li>
<a href="/fixtures">
<span class="fa fa-calendar"></span>
<span class="sidebar-title">Fixtures</span>
</a>
</li>
<li>
<a href="/players">
<span class="glyphicon glyphicon-book"></span>
<span class="sidebar-title">Players</span>
</a>
</li>
</ul>
Am I missing something in my jQuery to keep the class on the desired li?

Your JS is losing context with the refresh.
What you can do is run another function on load to check which url you're on, and set active state based on that. Something like this:
var setDefaultActive = function() {
var path = window.location.pathname;
var element = $(".sidebar-menu a[href='" + path + "']");
element.addClass("active");
}
setDefaultActive()

My solution is based on this link.
I needed nav pills to remain active after page refresh.
You can probably format this to fit your needs.
$(document).ready(function () {
// On page load
$('a[data-toggle="pill"]').on('show.bs.tab', function (e) {
// Get the id for the pill that was last shown and set it to local storage
localStorage.setItem('activeLink', $(e.currentTarget).attr('id'));
});
// After page loaded
// Get the id for the pill from local storage
var activeLink = localStorage.getItem('activeLink');
// If it's there, click it
if (activeLink) {
$(`#${activeLink}`).click();
}
});

Related

How to change active class on li element in JQuery and redirect the user to the specified page when li elelment is clicked?

I have the the following in my script tag. However, whenever I click the on test.php or test2.php li links, I am not redirected to the respective pages.
However, the active class changes from the index.php file to the test.php or test2.php file depending on which link has been clicked but I am not directed to the page. I attempted to the solutions in the following links, but now of them produce the desired result that I want, which is to redirect me to the page clicked and update the active class to the li element.
How to change active class while click to another link in bootstrap use jquery?
Active link after click
Whenever I uncomment this line e.preventDefault(), I am able to navigate to the link that have been click but the active class is not updated to the the
li elememnt clicked, but when the said line is commented, I am not able to navigate to the page clicked, instead, the active class is updated on the li element clicked.
<div class="menu">
<ul class="list">
<li class="header">MAIN NAVIGATION</li>
<li class="active">
<a href="index.php">
<i class="material-icons">home</i>
<span>Home</span>
</a>
</li>
<li class="">
<a href="test.php">
<i class="material-icons">group</i>
<span>Test</span>
</a>
</li>
<li class="">
<a href="test2.php">
<i class="material-icons">people</i>
<span>Test2</span>
</a>
</li>
</ul>
</div>
And the script code:
$(document).ready(function () {
$('.menu .list a').click(function(e) {
$('.menu li.active').removeClass('active');
var $parent = $(this).parent();
$parent.addClass('active');
e.preventDefault();
});
});
The contents of test.php are as follows:
<body class="theme-red">
<nav class="navbar">
<?php include_once('navbar.html'); ?>
</nav>
<section>
<aside id="leftsidebar" class="sidebar">
<?php include_once('left-side-bar.html');?>
</aside>
</section>
<section class="content">
<div class="container-fluid">
<div class="row clearfix">
<table id="tbl-users" class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tfoot>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</tfoot>
<tbody>
<?php
$accounts = get_details();
foreach($accounts as $acc){
?>
<tr>
<td><?php echo $acc['id']; ?></td>
<td><?php echo $acc['name']; ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
</section>
</body>
Why is the problem arising?
The problem arises that, when you use e.preventDefault() on click of
anchor tag, the default behaviour is to redirect the page and that's
why the page doesn't load but the active class gets added. But when
you don't use e.preventDefault(), the page redirects immediately
and the change you did happen but before it was redirected and not
for the new page(which could be redirected current page or some other page), that's why you can't see the class active added to
it.
.
How to fix the problem?
Well, there are a couple of ways to go about it. I'd say that from the
test.php or test2.php return a value, which you can validate against
the javascript with if-else conditions, if the value matches you make
that li class as active.
Here's the changes you need to make:
Add a span on each of your pages to which you have hyperlinked i.e test.php, test2.php, etc. having text the same as your hyperlink in the anchor tag so for test.php add a span as:
<span id="curpage" style="display:none;">test.php</span>
Then, add a script at the end of your body tag (you may be able to add this script in a seperate file and include in all of your php files using <?php include(".."); ?> :
$('a[href=\"' + $("#curpage").text() + '\"]').parent().addClass("active");
Here's a sample code, that you can try and implement. Make 2 files in
the same directory named as a.html having the code:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<span id="curpage" style="display:none;">a.html</span>
<div class="menu">
<li>1</li>
<li>2</li>
</div>
<script>
$('a[href=\"' + $("#curpage").text() + '\"]').parent().css("color","red");
</script>
</body>
</html>
And b.html having the code:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<span id="curpage" style="display:none;">b.html</span>
<div class="menu">
<li>1</li>
<li>2</li>
</div>
<script>
$('a[href=\"' + $("#curpage").text() + '\"]').parent().css("color","red");
</script>
</body>
</html>
And now when you change the pages by clicking the link, you can see
how the color of bullet changes.
I don't think you should be changing the "active" class just when the li links are clicked. Think that when you redirect your users to a specific page from another, the li links "OnClick" event won't be fired at all, hence, the active menu link won't be displayed appropriately.
Now, what I usually do to solve this issue (don't know if it's the most elegant solution, but it works) is to place a tag at the top of each html content template (I'm assuming you're using templates for the Header, Footer and Content here), I give it a descriptive ID, like "page-name" or "section", and add a data attribute to it with the name of the menu link that this page "belongs" to:
<div id="page-name" data-page="home-page">
Then with JQuery you can ask for the div's data like this:
var current_page = $("#page-name").data("page");
And simply alter the menu links class depending on what page the user is currently in:
// remove the "active" class from ALL the links first
$(".menu li a").removeClass("active");
if (current_page === "home-page") {
// add the "active" class just to the link you want
$("#home-page-link").addClass("active")
}
Of course, you would do that with a switch and you would have to load the js file on ALL pages (that's why the use of the Header template is so important, since you would just need to include it once). Also, in the html "data-page" attribute, the "page" part can be anything, just remember to call it appropriately later.
Hope I helped.
To dynamically add a class, on page load, to the navigation item of the current page, consider:
Checking the current page url: $(location).attr('href') OR
$(location).attr('pathname')
Looping through anchor elements (a) of the navigation menu to
determine if any of the href attribute values match the current
page url with a conditional check using the .indexOf() method:
if(anchorEl.indexOf(currentPageUrl) >= 0)
If any do, add the required class, using the .addClass() method:
$(this).addClass('current');
Code Snippet Demonstration:
Note: Intended for the sake of demonstration
The code snippet embedded below uses specific urls to provide a working example and to demonstrate the intended functionality. Adjust accordingly to apply to a given production environment.
$(document).ready(function () {
var currentPageUrl = $(location).attr('href'), // store current page url in variable
anchorEl;
$('.menu a').each(function(){
anchorEl = $(this).attr('href'); // store href atribute of current anchor element in iteration
console.log('anchor link url:',anchorEl);
console.log('current url of window:',currentPageUrl);
if(anchorEl.indexOf(currentPageUrl) >= 0) { // if anchor element contains
$(this).addClass('current');
console.log('class "current" was added.');
}
});
});
/*
Note:
$(location).attr('href') = full absolute path (https://stacksnippets.net/js)
$(location).attr('pathname') = relative path (/js)
*/
.current {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
<ul class="list">
<li>
<a href="https://stacksnippets.net/foobar1">
<span>foobar #1</span>
</a>
</li>
<li>
<a href="https://stacksnippets.net/foobar2">
<span>foobar #2</span>
</a>
</li>
<li>
<a href="https://stacksnippets.net/js">
<span>This should be the <em>current</em> url</span>
</a>
</li>
</ul>
</div>
You should know e.preventDefault() will prevent default behavior of that object which called on it (redirect in this case). So you are preventing your application from redirect to that href you specified.
You can change your function code like this:
$(document).ready(function () {
$('.menu .list a').click(function(e) {
$('.menu li.active').removeClass('active');
var $parent = $(this).parent();
$parent.addClass('active');
e.preventDefault();
//Here is needed change
location.href = $(this).attr('href');
});
});
Edit 1:
So you can work like this approach:
1) Specify a class name for each li tag
2) Send the class name that must has active class after redirection and page load
3) Read the passed class name from url and add/remove to/from your li tags
So your html code will be as following:
<div class="menu">
<ul class="list">
<li class="header">MAIN NAVIGATION</li>
<li class="home active">
<a href="index.php">
<i class="material-icons">home</i>
<span>Home</span>
</a>
</li>
<li class="group">
<a href="test.php">
<i class="material-icons">group</i>
<span>Test</span>
</a>
</li>
<li class="people">
<a href="test2.php">
<i class="material-icons">people</i>
<span>Test2</span>
</a>
</li>
</ul>
</div>
If you need to script code according to this solution which I explained, so I will update my answer.
Edit 2:
You need to have below script codes in your file:
function setActiveClass() {
//Remove active class from all li tags
$('.menu li.active').removeClass('active');
//Find current url
var url = $(location).attr('href');
if (url.contains("activeClass")) {
//Find the index of active class in url
var start = url.indexOf("#activeClass");
//Add 6 unit to start index because of the longest class name is people which has 6 character
var end = start + 6;
//Fetch passed class name from url
var className = url.substring(start, end);
//Add active class corresponding to passed class name
if(className.contains("home"))
$(".home").addClass('active');
else if(className.contains("group"))
$(".group").addClass('active');
else
$(".people").addClass('active');
} else {
//Add active class for default mode (when we have not any redirect yet)
$("#defaultLiTag").addClass('active');
}
}
$(document).ready(function () {
//Call the function
setActiveClass();
$('.menu .list a').click(function(e) {
e.preventDefault();
var classNameOfParent = $(this).parent().attr('class');
var classNameToBePassedByUrl = "home";
if(classNameOfParent.contains("group"))
classNameToBePassedByUrl = "group";
else if(classNameOfParent.contains("people"))
classNameToBePassedByUrl = "people";
location.href = $(this).attr('href') + "#activeClass=" + classNameToBePassedByUrl;
});
});
i had the same problem after a lot of searching i could find this solution in this link i hope it could help you. Although you should remove class active and add class active to clicked navbar item ,you should use location.href to add active class when the new page reload.
https://santosh-shah.com/add-class-active-page-refresh-jquery/

Clicking outside of an element to hide it, doesn't work with multiple elements

I want to hide multiple navigation bars when clicked outside of it, it makes sense to do so, But only one of them hides for one obvious reason.
HTML:
<nav class="navigation">
<ul>
<li><b>Aken</b></li>
<li class="right dropdown">
<a href="#" class="navigation-link nav-trigger">
Akar Muhamad
<img class="profile-picture" src="http://placehold.it/30x30/3498db/333">
<i class="fa fa-caret-down" aria-hidden="true" style="position: relative; right: 3%;"></i>
</a>
<div class="dropdown-content">
Profile
Settings
Logout
</div>
</li>
<li class="right dropdown">
<a href="#" class="navigation-link nav-trigger">
Akar Muhamad
<img class="profile-picture" src="http://placehold.it/30x30/3498db/333">
<i class="fa fa-caret-down" aria-hidden="true" style="position: relative; right: 3%;"></i>
</a>
<div class="dropdown-content">
Profile
Settings
Logout
</div>
</li>
</ul>
</nav>
JS:
$('.nav-trigger').on('click', function() {
// Loop through all the drop-downs, and make all of them invisible
// Except the one we clicked on.
$(this).siblings('.dropdown-content').toggleClass('visible');
var that = this;
$('.dropdown').each(function() {
if (that != this) {
$(this).siblings('.dropdown-content').removeClass('visible');
}
});
});
// TODO: Fix a bug where it doesn't work on multiple navigation bars.
$(document).on('click', function(event) {
if(event.target !== $('.nav-trigger')[0]) {
$('.dropdown').each(function() {
$(this).find('.dropdown-content').removeClass('visible');
});
}
});
Now, as you can see, I passed 0 as an index to check. But what I want is to loop through all of them and use the index as the key to that. Whenever I do that, it doesn't work at all, It also disables the click to show the navigation content function too.
Here's the JSBin.
You actually don't have to use loops here and you don't need to know the index.
$('.nav-trigger').on('click', function() {
// remove visible class from each .dropdown-content:
$('.dropdown-content').removeClass('visible');
// add visible class to .dropdown-content next to the clicked .nav-trigger:
$(this).siblings('.dropdown-content').addClass('visible');
});
$(document).on('click', function(event) {
// check if the clicked element is .nav-trigger:
$(event.target).is('.nav-trigger') ||
// if not, remove visible class from each .dropdown-content:
$('.dropdown-content').removeClass('visible');
});
JSFiddle Demo
Remove the loops and simply hide all of the dropdowns. Then add back the one you care about if necessary.
This code stores the dropdown visibility at click and uses it to toggle the visibility after hiding the dropdown content. This means that clicking the header will both open and close the dropdown.
$('.nav-trigger').on('click', function(event) {
// store current dropdown state
var visible = $(this).siblings('.dropdown-content').hasClass('visible');
// hide all dropdowns
$('.dropdown .dropdown-content').removeClass('visible');
// if we were visible, hide, and vice-versa
$(this).siblings('.dropdown-content').toggleClass('visible', !visible);
// prevent document handler from being fired
event.stopPropagation();
});
// hide all dropdowns if click propagates to document
$(document).on('click', function(event) {
$('.dropdown .dropdown-content').removeClass('visible');
});
JSBin

Removing and adding Classes on Dropdown Menus on Hover

I have a Navigation built that have drop down menus,
HTML STRUCTURE LIKE SO
<li class="c-header__subnav-item c-header__subnav-item-is-hidden c-header__subnav-item-is-visible-md">
<a class="c-header__subnav-links u-caps js-c-header__subnav-trigger" href="#">
Action Review Review
<i class="fa fa-angle-down fa-lg c-btn__icon-right-sm"></i>
</a>
<ul class="c-header__subnav-dd">
<li class="c-header__subnav-dd-item">
<a class="c-header__subnav-links c-header__subnav-links--dd" href="#">
Overview
</a>
</li>
<li class="c-header__subnav-dd-item">
<a class="c-header__subnav-links c-header__subnav-links--dd" href="#">
Review Form
</a>
</li>
<li class="c-header__subnav-dd-item">
<a class="c-header__subnav-links c-header__subnav-links--dd" href="#">
Performance Card
</a>
</li>
<li class="c-header__subnav-dd-item">
<a class="c-header__subnav-links c-header__subnav-links--dd" href="#">
Recent Recordings
</a>
</li>
</ul>
</li>
When You Hover On the a.js-c-header__subnav-trigger
It addes a class to its self as well as its sibling ul ( the dropdown menu)
This is perfect but since the hover is triggered on the 'a' element If I toggle the class when and I go to hover on the drop down menu it gets removed before I can because of hovering off the 'a' element.
If I just add the classes and do not use toggle how would I remove both classes once I hover off the A element or Dropdown menu.
What needs to be achieved is
1.) If main nav link is hovered add an active class to itself and drop down is triggered and can be seen. If you hover out WITHOUT engaging the dropdown both active and dropdown class are removed
2.) If main nav link is hovered add an active class to itself and if dropdown IS engaged by user keep both classes until dropdown is hovered out of or 'A' Element.
CURRENT JQUERY CODE
;(function($, window, document, undefined) {
var $win = $(window);
var $doc = $(document);
var $classes = {
SubNavTrigger : 'js-c-header__subnav-trigger',
SubNavItemActive : 'c-header__subnav-item-is-active',
SubNavDropDown : 'c-header__subnav-dd',
SubNavDropDownActive : 'c-header__subnav-dd-is-active'
};
var _isMobile = false;
_isMobile = ($win.width() <= 1024) ? true : false;
// Check if user is on touch on page load
// if isMobile use click events
// if not mobile use hover events
if(_isMobile) {
$("." + $classes.SubNavTrigger).on('click', function(){
if ( $(this).hasClass( $classes.SubNavItemActive ) ){
// If Item has active class removeClass
$(this).removeClass( $classes.SubNavItemActive )
} else {
// If Item does not have active class addClass
$(this).addClass($classes.SubNavItemActive);
} //End if
// Add Active Class To Subnav.
$(this).siblings().toggleClass($classes.SubNavDropDownActive);
});
} else {
$("." + $classes.SubNavTrigger).on('hover', function(){
$(this).addClass($classes.SubNavItemActive);
// Add Active Class To Subnav.
// If set to toggle impossible to hover on this menu.
$(this).siblings().addClass($classes.SubNavDropDownActive);
});
}
})(jQuery, window, document);
Thanks In Advance for any help.
Live Site Link to see
http://100dc.vincebrown.me/integrity-pledge
So I would make a few changes, I would move the s-c-header__subnav-triggerclass to the parent li. I would then change the jquery to use the hover(in,out). The in function would look something like
function () {
$(this).addClass($classes.SubNavItemActive);
// Add Active Class To Subnav.
$(this).children().addClass($classes.SubNavDropDownActive);
}
and the out
function () {
$(this).removeClass($classes.SubNavItemActive);
// Add Active Class To Subnav.
$(this).children().removeClass($classes.SubNavDropDownActive);
}
Here is a jsfiddle

jQuery adding active class to nav, now nav not working

So, I'd like my breadcrumb nav to show the user which page he/she is on by having the be a different color according to the page they are on. I.e. if on home, the home link is gray whilst the others remain black.
To do this I've added the following code to my app:
$(function(){
$('.breadcrumb li a').on('click', function(e){
e.preventDefault(); // prevent link click if necessary?
var $thisA = $(this);
var $li = $thisA.parent('a');
if (!$thisA.hasClass('active'))
{
$li.find('a.active').removeClass('active');
$thisA.addClass('active');
}
})
})
However, with the above code it never releases the active class when I also click events for example they end up both just being gray. Also, the page doesn't switch it stays on home page but with home and events grayed out.
The css:
.breadcrumb li a.active { color: #999999;}
The html
<ul class="breadcrumb">
<li>
<a class="active" href="/profiles"> Home</a>
</li>
<li>
<a class="active" href="/events"> Events</a>
</li>
<li>
Messages
</li>
<li>
My Profile
</li>
</ul>
Change
var $li = $thisA.parent('a');
to
var $li = $thisA.parents('ul');
because this line
$li.find('a.active').removeClass('active');
looks for a child a.active and your original $li would be null because your original line is trying to find a a that is a parent of the clicked a.
EDIT
Resources on highlighting the current page:
http://hicksdesign.co.uk/journal/highlighting-current-page-with-css
$("a[href*='" + location.pathname + "']").addClass("current"); from highlighting the current page in a list of links using css / html
http://www.eznetu.com/current-link.html#

Show/Hide content based on anchor - Almost there

I am very close but just can't see what I am missing in the jQuery script to only display the correct block of content based upon the anchor clicked and want to display initially to a visitor the first block of content from the anchors. Any help is appreciated.
I have dynamically generated anchor links with a class of .link
The content is also dynamically generated and each anchor point (A, B, C...) has it's content contained in a ul class of .test-full-list. Any help is appreciated.
Generated content:
Anchor links:
<span class="link">A</span>
<span class="link">B</span>
Content:
<div class="test-listing-container">
<ul class="test-full-list">
<ul class="test-category-list">
<a name="A"></a>
<div class="anchor-header">- A -</div>
<li id=test-list>
Some Link 1
Some Link 1
</li>
</ul>
</ul>
</div>
Script:
jQuery(document).ready(function () {
jQuery('.test-listing-container').hide();
jQuery('.link a').click(function () {
var jQuerydiv = jQuery('.test-full-list').eq(jQuery(this).index('.link a'));
jQuerydiv.show('.test-full-list'); // show the relevant div
});
});
If you're bringing in content dynamically, your .click() will not work. This is because the element you are trying to attach the click to hasn't been generated.
You can replace this:
jQuery('.link a').click(function() {
With this:
jQuery('.test-listing-container').on('click', '.link a', function() {
If that doesn't work:
jQuery(document).on('click', '.link a', function() {
Edit: Adding a fiddle to demo the code: http://jsfiddle.net/Fm6bR/1/
Assuming you can't change the markup slightly, you may do the following
A
B
<div class="test-listing-container">
<ul class="test-full-list">
<ul class="test-category-list">
<a name="A"></a>
<div class="anchor-header">- A -</div>
<li id=test-list>
Some Link 1
Some Link 1
</li>
</ul>
</ul>
</div>
jQuery(document).ready(function(){
jQuery('ul.test-category-list').hide();
jQuery('ul.test-category-list').first().show(); //show the first one by default
jQuery(document).on('click', '.link a', function (evt) {
var $a = jQuery(evt.currentTarget),
name = $a.attr('href').substr(1),
$a2 = jQuery('.test-listing-container').find('a[name="' + name + '"]'),
$ul = $a2.parents('ul.test-category-list').first();
jQuery('ul.test-category-list').hide(); // hide all
$ul.show(); // show the relevant one
});
});
Generate the content with an id based on the anchor name or some other unique identifer of the content. set data-content on each link to the id of the contents id. then use jquery to get the content by using .data function on the link in the click function
HTML
<span class="link">A</span>
<span class="link">B</span>
<div class="test-listing-container">
<ul class="test-full-list" id="fulllistA">
<ul class="test-category-list">
<li id=test-list>
Some Link 1
Some Link 1
</li>
</ul>
</ul>
</div>
Javascript
jQuery(document).on("click",".link a",function(e){
e.preventDefault();
e.stopPropagation();
var content = jQuery("#"+jQuery(this).data("content"));
jQuery(".test-listing-container > ul").not(content).hide(); // hide the others.
content.show();
});

Categories

Resources