How can I keep class active after refreshing the page (using jQuery) - javascript

I have been searching for whole day and found several examples but none of them work correctly. I have a navigation bar and I want to keep class active after clicking on it and refreshing page but it gets lost.
This is my code:
HTML
<li class="sub-menu" style="border-bottom: 1px solid grey;">
<a class="menuItem active" href="#Url.Action("Index", "Administrator")">
<i class="fa fa-th"></i>
<span>Index</span>
</a>
</li>
<li class="sub-menu">
<a class="menuItem normal" href="#Url.Action("Products", "Administrator")">
<i class="fa fa-shopping-cart"></i>
<span>product</span>
</a>
</li>
Javascript
var retrievedObject = localStorage.getItem('classChange');
if (retrievedObject) {
$('.menuItem').addClass(retrievedObject)
}
$(".menuItem").click(function () {
if ($(this).hasClass("normal")) {
$(this).removeClass('normal').addClass('active');
localStorage.setItem('classChange', 'active');
} else {
$(this).removeClass('active').addClass('normal');
localStorage.setItem('classChange', 'normal');
}
});
I expected to change class on active after click but all classes change after click, I understand why it happens but don't know how to fix it.

Can you give each element an id value and, in the function, store in the local storage the id of the element and the class? Then, on reload check for the both id's?
And if you need for more elements you can save an array of the id's and then use it to loop between all id's if necessary.
So something like this:
var ids = ['id1','id2'];
for(i of ids) {
var retrievedObject = localStorage.getItem(i);
if (retrievedObject) {
var id = "#" + i;
$(id).addClass(retrievedObject);
}
}
$(".menuItem").click(function (event) {
if ($(this).hasClass("normal")) {
$(this).removeClass('normal').addClass('active');
localStorage.setItem('classChange', 'active');
} else {
$(this).removeClass('active').addClass('normal');
localStorage.setItem(event.target.id, 'normal');
}
});

The code
if (retrievedObject) {
$('.menuItem').addClass(retrievedObject)
}
should be wrapped on jQuery.ready().

Related

Disable dropdown item with CSS or Javascript

I need to disable, deactivate or at least hide a dropdown item called Private request and I can only use CSS or Javascript to do so.
When I inspect the dropdown item it has the class a.js-dropdown-list. But every item in my dropdown has this class. So I can't just use {display: none;} because it will hide all options. Is there no more specific ID for every item in the drop down or can I deactivate items with Javascript?
Drop Down looks like this:
Here the code (1st block is for the picker field, 2nd for the drop-down menue):
<div id="js-organization-picker">
<sd-select class="js-share-with-organisation-picker is-private" data-type="link" data-id="customfield_10203" data-value="38" data-options="[{"label":"Private request","styleClass":"is-private","icon":"locked"},{"label":"Share with Testorganisation","value":38,"icon":"unlocked"}]" resolved="">
<a id="js-customfield_10203-dropdown-trigger" class="aui-dropdown2-trigger aui-button aui-button-link js-trigger customfield_10203-trigger select-dropdown-trigger aui-alignment-target aui-alignment-element-attached-top aui-alignment-element-attached-left aui-alignment-target-attached-bottom aui-alignment-target-attached-left active aui-dropdown2-active aui-alignment-enabled" aria-controls="customfield_10203-dropdown" aria-haspopup="true" role="button" tabindex="0" data-aui-trigger="" data-dropdown2-hide-location="js-customfield_10203-dropdown-container" resolved="" aria-expanded="true" href="#customfield_10203-dropdown">
<span class="aui-icon aui-icon-small aui-iconfont-locked">
: : before
</span> Private request
: : after
</a>
<input name="customfield_10203" type="hidden" class="js-input" value="">
<div id="js-customfield_10203-dropdown-container" class="hidden"></div>
</sd-select>
</div>
<div id="customfield_10203-dropdown" class="aui-dropdown2 filter-dropdown aui-style-default js-filter-dropdown select-dropdown aui-layer aui-alignment-element aui-alignment-side-bottom aui-alignment-snap-left aui-alignment-element-attached-top aui-alignment-element-attached-left aui-alignment-target-attached-bottom aui-alignment-target-attached-left aui-alignment-enabled" role="menu" aria-hidden="false" data-id="customfield_10203" resolved="" style="z-index: 3000; top: 0px; left: 0px; position: absolute; transform: translateX(602px) translateY(918px) translateZ(0px);" data-aui-alignment="bottom auto" data-aui-alignment-static="true">
<div role="application">
<ul class="aui-list">
<li>
<a class="js-dropdown-item " href="#">Private request</a>
</li>
<li></li>
<li>
<a class="js-dropdown-item " href="#" data-value="38">Share with Testorganisation</a>
</li>
<li></li>
</ul>
</div>
</div>
E.g. you could give the dropdown item ids to identify them. In HTML this would look like this: <p id="yourIdHere"></p>
You can access this item through Javascript using the document.getElementById() function like this: document.getElementById('yourIdHere').style.display = 'none';
If you can't edit the existing html code, youi have to get the element by it's name/value. This is a bit difficult. You have to iterate through all elements of that type and evaluate each name/value. If you have found the one, you was looking for, you can edit/hide it. You would do so (untested):
var elements = document.getElementsByTagName('div'); //div will be the name of the tag of your elements in the dropdown list
var length = elements.length;
for (var i=0, item; item = elements[i]; i++) {
if(item.value == "Private request") { //"Private request" is the name of the element we are looking for
item.style.display = 'none'; //Hide the element
}
}
You could loot trough all 'js-dropdown-items', check its innerText for 'Private request' and set its parentNodes display-property to 'none':
var list = document.getElementsByClassName('js-dropdown-item');
for(var i = 0; i < list.length; i++){
if(list[i].innerText === 'Private request') list[i].parentNode.style.display = 'none';
}
<ul class="aui-list">
<li>
<a class="js-dropdown-item " href="#">Private request</a>
</li>
<li></li>
<li>
<a class="js-dropdown-item " href="#" data-value="38">Share with Testorganisation</a>
</li>
<li></li>
</ul>
VannillaJS Solution document.querySelectorAll(".aui-list > li")[0].style.display = "none";
Welcome!
If I get you right there are plenty of elements with the same ID js-dropdown-list and you want to hide a specific one and there is no additional class for the element and you're not allowed to add specificity to it, let's say by adding of an additional class, you can do the following:
Grab all elements with this id by:
let elements = document.querySelectorAll('.js-dropdown-list'); // this is an array of these elements
let elementToHide = elements[n] // whene n is the number of that element
//hiding the element
elementToHide.style.display = 'none';
Hope that helps!
NOTE: I believe you will have to actually hide it OR use whatever you are using for this pseudo drop down (there was no reference in the question) to manage the disabled state if it provides that. Reference: https://www.w3.org/TR/2014/REC-html5-20141028/disabled-elements.html
Get the element by its text and then hide it. Might need the parent but this directly answers the question. Note this could all be wrapped in a function and then called from where you wish.
function HideByText(elId, findText) {
let group = document.getElementById(elId).getElementsByClassName('js-dropdown-item');
let found = Array.prototype.filter.call(group, function(el) {
return el.innerText === findText;
});
found.forEach(function(el) {
el.style.display = 'none';
});
return found;// in case you need the elements ref.
}
let foundFiltered = HideByText('customfield_10203-dropdown', 'Private request');
<div id="customfield_10203-dropdown" class="aui-dropdown2 filter-dropdown aui-style-default js-filter-dropdown select-dropdown aui-layer aui-alignment-element aui-alignment-side-bottom aui-alignment-snap-left aui-alignment-element-attached-top aui-alignment-element-attached-left aui-alignment-target-attached-bottom aui-alignment-target-attached-left aui-alignment-enabled"
role="menu" aria-hidden="false" data-id="customfield_10203" resolved="" data-aui-alignment="bottom auto" data-aui-alignment-static="true">
<div role="application">
<ul class="aui-list">
<li>
<a class="js-dropdown-item " href="#">Private request</a>
</li>
<li></li>
<li>
<a class="js-dropdown-item " href="#" data-value="38">Share with Testorganisation</a>
</li>
<li></li>
</ul>
</div>
</div>
Alternate for parent would be:
Change el.style.display = 'none'; to
if (node.parentElement) {
el.parentElement.style.display = 'none';
}
Have you tried using CSS? Not an ideal solution, but it might be better than using JS for this.
#js-organization-picker + .aui-dropdown2 .aui-list li:first-child {
display: none;
}
If you need to hide the first 2 elements, you could do something like:
#js-organization-picker + .aui-dropdown2 .aui-list li:first-child,
#js-organization-picker + .aui-dropdown2 .aui-list li:first-child + li {
display: none;
}

JQuery/JavaScript: how to retain active nav state after link?

I've found many posts on how to add the active class to a nav link via jquery, but nothing on how to maintain the active state after the nav link is clicked.
Using code found on this site, I'm removing and adding the active class onclick. In an attempt to keep this active state after navigating/reloading, my thought is to set session variables via onclick, and re-add the active class.
What I have is not working.
This seems to work, but doesn't seem to be best-practice, by today's standards.
HMTL:
<nav>
<a href="about.xhtml" id="about" >About</a>
<span class="nav_divide"></span>
<a href="work.xhtml" id="work" >Work</a>
<span class="nav_divide"></span>
<a href="mission.xhtml" id="mission" >Mission</a>
<span class="nav_divide"></span>
<a href="contact.xhtml" id="contact" >Contact</a>
</nav>
CSS:
nav a.active {
border-bottom: 3px solid #d10f0f;
}
Script:
//Check for session variables.
$(document).ready(function() {
//If 'page' session is defined
if (window.sessionStorage.pageSession) {
// make selected nav option active.
var activeTab = '#' + window.sessionStorage.pageSession;
$(activeTab).addClass('active');
} else {
// If pageSession is not defined, you're at home
window.sessionStorage.pageSession = ('page', 'home');
}
//Set link location for page refresh/reload
});
// Place or remove nav active state.
$(document).on('click','nav a',function(){
//Set 'page' and 'link' variables based on nav values.
var page = this.id;
var link = this.href;
// Set 'page' and 'link' session variables based on nav values.
var window.sessionStorage.pageSession = ('page', page);
var window.sessionStorage.linkSession = ('link', link);
// Update classes.
$('nav .active').removeClass('active');
$(this).addClass('active');
// Link to nav ahref.
window.location = sessionStorage.linkSession;
});
You can use localStorage! this is an example:
//Check for session variables.
$(document).ready(function() {
// Set paramenters obj for initialization
let paramObj = {page:'current-page-name',link:location.href};
// Initialize pageSession obj to storage the current page
localStorage.setItem('pageSession', JSON.stringify(paramObj));
// Retrieve page session settings updated
let pageStorage = localStorage.getItem('pageSession') != undefined ? JSON.parse(localStorage.getItem('pageSession')) : paramObj;
// make selected nav option active.
let activeTab = '#' + pageStorage.page;
$(activeTab).addClass('active');
//Set link location for page refresh/reload
$(document).on('click','nav a',function(e){
e.preventDefault();
//Set 'page' and 'link' variables based on nav values.
let page = JSON.parse(localStorage.getItem('pageSession')).page;
let link = JSON.parse(localStorage.getItem('pageSession')).link;
// Set 'page' and 'link' session variables based on nav values.
localStorage.setItem('pageSession', JSON.stringify({page:$(this).attr('id'), link:$(this).attr('href')}));
// Update classes.
$('nav .active').removeClass('active');
$(this).addClass('active');
// Link to nav ahref.
window.location = $(this).attr('href');
});
});
nav a.active {
border-bottom: 3px solid #d10f0f;
}
<nav>
<a href="javascript:;" id="home" >Home</a>
<span class="nav_divide"></span>
<a href="javascript:;" id="about" >About</a>
<span class="nav_divide"></span>
<a href="javascript:;" id="work" >Work</a>
<span class="nav_divide"></span>
<a href="javascript:;" id="mission" >Mission</a>
<span class="nav_divide"></span>
<a href="javascript:;" id="contact" >Contact</a>
</nav>
There are a lot of ways for doing that. This is only one of ways!
--------------- EDITED ---------------
Now the code initialize pageSession on every page, so the JSON.parse(...) was solved!
Try it here jsfiddle. Now it works!
I hope it help.

jQuery detect class of child element

I have a button, which when clicked I want to display two additional buttons Cancel and Confirm.
When o class is added a negative margin left is added and the button disappears.
$('.a_bttn_inner_action').click(function() {
if ($(this).children().find('.button')) {
$(this).parent().find('.button').queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).removeClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).removeClass('o');
next();
});
} else if ($(this).children().find('.confirm.no')) {
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.button').queue(function(next) {
$(this).removeClass('o');
next();
});
}
});
li.o {
margin-left: -800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bttn_inner_action">
<ul class="action">
<a href="#" class="a_bttn_inner_action">
<li class="button ">Do something...</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm no o">Cancel!</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm yes o">Confirm...</li>
</a>
</ul>
</div>
With the jQuery I have a problem here if($(this).children().find('.button')) and here else if($(this).children().find('.confirm.no')).
I want to detect which of the current element's children were selected by the class of the li element.
Is this possible?
I've tried if($(this).children().attr('class') == 'button') also doesn't work.
I believe this is what you are looking after. For checking children you can use
.find('.button').length
it will give back 0 or a positive integer so you can use it inside an if. In your code the first if was always true, so the other would never run.
$('.a_bttn_inner_action').click(function() {
if ($(this).find('.button').length) {
$(this).parent().find('.button').queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).removeClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).removeClass('o');
next();
});
} else if ($(this).find('.confirm.no').length) {
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.button').queue(function(next) {
$(this).removeClass('o');
next();
});
}
});
li.o {
margin-left: -800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="">
<ul class="action">
<a href="#" class="a_bttn_inner_action only-here">
<li class="button ">Do something...</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm no o">Cancel!</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm yes o">Confirm...</li>
</a>
</ul>
</div>
To simply know which button is clicked, you can use the target property of the click event to get the html element clicked =>
$('.elements').on('click', function(e){
var $targer = $(e.target);
});
You can use the hasClass() jQuery method on a jQuery element, or the is() method, to test the properties of an jQuery/html element.
I rewrite your code snippet keeping the logic, but changing some html. Look at the tests of the clicked element (target).
Your html is malformed, because children of a list ul must be an li element.
So your html should be something like this :
<div class="bttn_inner_action">
<ul class="action">
<li class="a_bttn_inner_action">
Do something...
</li>
<li class="a_bttn_inner_action">
Cancel!
</li>
<li class="a_bttn_inner_action">
Confirm...
</li>
</ul>
</div>
$('.button').click(function(e) {
var $target = $(e.target);
if ($target.hasClass('do-something')) {
$('.button.confirm.yes').delay(300).queue(function(next) {
$(this).parent('li').removeClass('o');
next();
});
$('.button.confirm.no').delay(100).queue(function(next) {
$(this).parent('li').removeClass('o');
next();
});
} else if ($target.is('.confirm.no')) {
$('.button.confirm.yes').delay(300).queue(function(next) {
$(this).parent('li').addClass('o');
next();
});
$('.button.confirm.no').delay(100).queue(function(next) {
$(this).parent('li').addClass('o');
next();
});
}
});
li.o {
margin-left: -800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bttn_inner_action">
<ul class="action">
<li class="li_bttn_inner_action">
Do something...
</li>
<li class="li_bttn_inner_action o">
Cancel!
</li>
<li class="li_bttn_inner_action o">
Confirm...
</li>
</ul>
</div>
The event listener can be optiomized. With $('.class').click() function, listener is attached to each .class elements. Use $('parentElement').on('click', 'subElement', function(e){...}) instead to attach just one event listener to a parent element.
See .on() function on jQuery doc.
You could just check the count of children with button class.
if ($(this).find('.button').length > 0) {
// there are some
}
children() gets all the direct child elements of the selected elements. find() gets all the child elements all the way down the hierarchy.
So $(this).children() is going to select all the <li> elements, and then find() is going to look through all of the child elements of those <li> and not at the <li> itself
What you want is just
$(this).find('.button').length
//or
$(this).find('.confirm.no').length
//or you could just find the li itself and then test for the class
var button = $(this).find('li');
if(button.is('.button')){
} else if(button.is(".confirm.no")){
}
Also note do not test against the return of children() or find() as both will return a new jQuery object wither or not anything was actually found, so the result will always test as truthy.
You could also just put the click handler on the LI themselves and not worry about the invalid wrapping them in an anchor tag
$('ul.action li').click(function() {
var $this = $(this);
if($this.is('.button')){
} else if($this.is('.confirm.no')){
}
});
The answer is the exists() function.
The following statement:
$(this).children().find('.button')
returns a JQuery object whose length is zero even there is no element selected.
So, if ($(this).children().find('.button')) is always going to be passed.
Either you can check the length of the return object or use JQuery exists() function.
Details are here.

Change div text (and revert back) on tab button click using jquery

I have two tabs like below image
On selection of tab i want to change the text of a div. If i select invoice i want to change value of credit card fee to 0 and if i select credit card it's value should revert back.(in above image it's $17.00)
Here is my html code
<ul class="nav nav-tabs payment-method-list" style="list-style-type: none;">
<li class="active" style="list-style-type: none;">
<a data-target="#payment-method-selector-creditcard" data-toggle="tab" data-type="creditcard" href="#">
Credit / Debit Card
</a>
</li>
<li class="" style="list-style-type: none;">
<a data-target="#payment-method-selector-invoice" data-toggle="tab" data-type="invoice" href="#">
Invoice
</a>
</li>
</ul>
<p>
Credit card fee code
<span class="pull-right cart-summary-handling-cost-formatted" id="service_charge">$17.00</span> //it's value will be dynamic
<span>Credit Card Fee </span>
Here is my jquery code
jQuery(document).ready(function() {
jQuery(".payment-method-list li a").click(function() {
var originaltext = jQuery("#service_charge").text();
if (jQuery('a[data-target="#payment-method-selector-invoice "]').parent().hasClass('active')) {
jQuery("#service_charge").text("0");
} else {
jQuery("#service_charge").text(originaltext);
}
});
});
But it's changing value to 0 when i click first invoice then credit card after that it's value is not changing back to original text.
As I'm new to jquery please help me what's wrong with this code.
jQuery(document).ready(function() {
jQuery(".payment-method-list li a").click(function() {
localStorage.setItem("originalBalance", jQuery("#service_charge").text());
if (jQuery('a[data-target="#payment-method-selector-invoice "]').parent().hasClass('active')) {
jQuery("#service_charge").text("0");
} else {
jQuery("#service_charge").text(localStorage.getItem("originalBalance"));
}
});
});
Try this. I am saving the original balance through localStorage.
Try check by data-type ,because your active class is changing when you clicked and checking your operator ...
jQuery(document).ready(function()
{
var originaltext= jQuery("#service_charge").text();
jQuery(".payment-method-list li a").click(function(){
if(jQuery(this).data("type") == "invoice")
{
jQuery("#service_charge").text("0");
}
else {
jQuery("#service_charge").text(originaltext);
}
});
});
You are getting the issue as once the text on input is updated when using .text(), next time it will return the updated text. You can to persist the originaltext in internal data cache using .data(), which can be fetched when required.
jQuery(document).ready(function() {
//Persists originaltext
var serviceChange = jQuery("#service_charge");
var originaltext = serviceChange.text();
serviceChange.data('originaltext', originaltext);
//Populate it using the method
//serviceChange.data('originaltext', getOriginalText());
jQuery(".payment-method-list li a").click(function() {
if (jQuery('a[data-target="#payment-method-selector-invoice "]').parent().hasClass('active')) {
serviceChange.text("0");
} else {
serviceChange.text(serviceChange.data('originaltext'));
}
});
});

How to dynamically add a class to li item and change its background color using javascript and css

Here I have a list, what I want to do is I need to change the list ( li ) background color to different one after click on a specific list item. the thing is once it click on the link page will be redirected and refresh. please can me suggest a solution for to get this done?
<div id="main-menu">
<ul id="main-menu-list">
<li id="menu-home">Home</li>
<li id="menu-profile">My Profile</li>
<li id="menu-dashboard">My Dashboard</li>
<li id="menu-search">Search</li>
</ul>
</div>
what i did for this :
Java Script :
var make_button_active = function()
{
//Get item siblings
var siblings =($(this).siblings());
//Remove active class on all buttons
siblings.each(function (index)
{
$(this).removeClass('active');
}
)
//Add the clicked button class
$(this).addClass('active');
}
//Attach events to menu
$(document).ready(
function()
{
$("#main-menu li").click(make_button_active);
}
)
CSS :
#main-menu-list li.active {
background: #0040FF;
}
It's a little difficult to tell exactly what you want to do, but here's some quick and dirty (and untested) code:
/// when we click on an `a` tag inside the `#main-menu-list`...
$('#main-menu-list').on('click', 'a', function(e) {
// stop the link from firing
e.preventDefault();
e.stopPropagation();
// change the list item's background to green
$(this).closest('li').addClass('myClassName').css('background-color', 'green');
// do anything else, e.g. load in pages via ajax...
});
You could use CSS to apply the green background color, instead of jQuery:
.myClassName { background-color: green; }
This will stop the page from navigating, and I don't know if that's your intention. If you want to check the currently-loaded page against the menu to find the current item, you could do this (on page load) instead:
var currentPage = window.location.pathname;
$('#main-menu-list').find('a[href^="' + currentPage + '"]').closest('li').addClass('active');
EDIT:
Your amended Javascript code can be simplified to the following:
$('#main-menu li').on('click', 'a', function (e) {
e.preventDefault();
e.stopPropagation();
// only do the following if the clicked link isn't already active
if(!$(this).closest('li').hasClass('active')) {
$(this).closest('ul').find('.active').removeClass('active');
$(this).closest('li').addClass('active');
// load in your content via ajax, etc.
}
});
JSFiddle example
For each page you can add a class to the current list item that has "where the user is"..
CSS:
.selectedItem{
background-color: orange;//whatever color your want for the selected tab..
}
Then for each of your pages,
say you're in Dashboard.html
your menu code will look like:
<div id="main-menu">
<ul id="main-menu-list">
<li id="menu-home">Home</li>
<li id="menu-profile">My Profile</li>
<li id="menu-dashboard" class="selectedItem">My Dashboard</li>
<li id="menu-search">Search</li>
</ul>
</div>
in profile.html:
<div id="main-menu">
<ul id="main-menu-list">
<li id="menu-home">Home</li>
<li id="menu-profile" class="selectedItem">My Profile</li>
<li id="menu-dashboard">My Dashboard</li>
<li id="menu-search">Search</li>
</ul>
</div>
and so on..
You need to change the background color when the document is loaded (i.e. in document.ready).
Then you need a mechanism to connect the currently loaded page to one of your list items.
$(document).ready(function(){
//get the url from the current location or in some other way that suits your solution
//perhaps use window.location.pathname
var moduleId = "dashboard" // hardcoded to dashboard to make the point :);
$("#menu-"+moduleId).css("background-color", "#ccc");
});
http://jsfiddle.net/9JaVn/1/

Categories