Bootstrap 4 remember tab - javascript

How can I get the browser to remember which tab the user was viewing when the page is refreshed or revisited ?
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#home" role="tab" aria-controls="home">Home</a>
Profile
Messages
Settings
<div class="tab-content">
<div class="tab-pane active" id="home" role="tabpanel">...</div>
<div class="tab-pane" id="profile" role="tabpanel">...</div>
<div class="tab-pane" id="messages" role="tabpanel">...</div>
<div class="tab-pane" id="settings" role="tabpanel">...</div>
</div>

This did the trick for me..
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var hash = $(e.target).attr('href');
if (history.pushState) {
history.pushState(null, null, hash);
} else {
location.hash = hash;
}
});
var hash = window.location.hash;
if (hash) {
$('.nav-link[href="' + hash + '"]').tab('show');
}
Creates sharable links using the URL hash.

This is the multiple tabs example :
$('a[data-toggle="tab"]').on('click', function (e) {
var theTabId = $(this).attr('href');
var activeTabs = (window.localStorage.getItem('activeTab') ? window.localStorage.getItem('activeTab').split(',') : []);
var $sameLevelTabs = $(e.target).parents('.nav-tabs').find('[data-toggle="tab"]');
$.each($sameLevelTabs, function (index, element) {
var tabId = $(element).attr('href');
if(theTabId != tabId && activeTabs.indexOf(tabId) !== -1){
activeTabs.splice(activeTabs.indexOf(tabId), 1);
}
});
//unique tabs
if (activeTabs.indexOf($(e.target).attr('href')) === -1) {
activeTabs.push($(e.target).attr('href'));
}
window.localStorage.setItem('activeTab', activeTabs.join(','));
});
var activeTabs = window.localStorage.getItem('activeTab');
if (activeTabs) {
var activeTabs = (window.localStorage.getItem('activeTab') ? window.localStorage.getItem('activeTab').split(',') : []);
$.each(activeTabs, function (index, element) {
$('[data-toggle="tab"][href="' + element + '"]').tab('show');
});
}

Here's one way you could do it. Obviously, this won't quite work since the snippet is on stackoverflow.com and the hash won't be appended to the url. I tested this locally though and it works.
Note: This will only work if you refresh the page or otherwise use the specific URL that refers to the tab to be opened. If you want it to "remember" the tab after you close the browser/tab or whatever, you would probably be best off using cookies or perhaps storing it in a database if you are dealing with client sessions.
//When the page loads, get the current # value and mark the li as "active" if the href attribute matches.
$(document).ready(function() {
var v = "#" + window.location.hash.substr(1);
$("#myTab li").each(function() {
var href = $(this).children().first().attr("href");
if (href == v) $(this).addClass("active");
else $(this).removeClass("active");
});
});
//Whenever we click on a li, remove all "active" classes and finally add "active" to the one we clicked.
$("#myTab li").on("click", function() {
$("#myTab li").each(function() {
$(this).removeClass("active");
});
$(this).addClass("active");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<ul class="nav nav-tabs" id="myTab">
<li>Home</li>
<li>Profile</li>
<li>Messages</li>
<li>Settings</li>
</ul>

If you want to save a value for after refresh, You can use cookie or sessionStorage (as said in comments). The easier is sessionStorage i think.
$('.tab-pane').click(function(){
sessionStorage.setItem("clicked", $(this).attr('id'));
});
And after page refresh, you can retrieve the saved value:
if(sessionStorage.getItem("clicked") != null)
var clickeId = sessionStorage.getItem("clicked")

I used local storage to store the active-tab-id and it works for me.
$('a[data-toggle="tab"]').on("click", function(e) {
localStorage.setItem("active-tab-id", $(e.target).attr("href"));
});
var activeTabId = localStorage.getItem("active-tab-id");
var activeTab = $(`a[href="${activeTabId}"]`);
if(activeTab.length == 1)
activeTab.tab("show");
else
$('a[data-toggle="tab"]')[0].click();
if your tab is not activated, by default it's clicked on the first tab.

Related

Active navigation class based on current URL problem

I have the following HTML menu:
<div class="nav">
<ul>
<li class="first">Home</li>
<li>Something</li>
<li>Else</li>
<li class="last">Random</li>
</ul>
<ul style="float:right;">
<li class="first last">News</li>
</ul>
</div>
</div>
And then I have this code:
jQuery(function($){
var current = location.pathname;
$('.nav ul li a').each(function(){
var $this = $(this);
// if the current path is like this link, make it active
if($this.attr('href').indexOf(current) !== -1){
$this.addClass('active');
}
})
})
The code is working great, but it has a problem. For example, if I see the Home page (www.example.com) then all of the menu links receives the active class. Another problem would be that it works great for www.example.com/something but it doesn't keep it active if I go to www.example.com/something/1 etc. Any idea how to fix this? Thanks in advance!
For home page add extra class 'default' in list like.
<li class="first default">Home</li>
jquery code.
jQuery(function($){
var current = location.pathname;
console.log(current);
//remove the active class from list item.
$('.nav ul li a').removeClass('active');
if(current != '/'){
$('.nav ul li a').each(function(){
var $this = $(this);
// if the current path is like this link, make it active
if(current.indexOf($this.attr('href')) !== -1 && $this.attr('href') != '/'){
$this.addClass('active');
}
})
}else{
console.log('home');
$('.default a').addClass('active');
}
})
Use the below jQuery code to add active class:
$(function() {
var pgurl = window.location.href.substr(window.location.href
.lastIndexOf("/") + 1);
$(".nav ul li a").each(function() {
if ($(this).attr("href") == pgurl || $(this).attr("href") == '')
$(this).addClass("active");
})
});
By using indexOf(), you are checking if the link's target is the same the current location.
What you want is not "the same URL" but "the same pattern", so I would tend to use a regular expression :
let re = new RegExp("^" + $(this).attr("href") + ".*");
if (re.test($current)) {
$(this).addClass("active");
}
Note that this would force you to create a separate solution for your link to the main page, else it would always be active.

Disable href link when containing #, but enable all others

So this mostly works, however, the only URL that works is what is specified as "Blog." All the anchor references with # are smooth scrolling on click but all my external links on my page aren't doing anything.
Can I write the prevent default in a way that only includes the href links with "#" in them? I have image links, etc throughout my page and want a simple method to manage it rather than pointing each url out.
<ul class="snip1143">
<li class>Home</li>
<li>About</li>
<li>Work</li>
<li>Blog </li
<li>Contact</li>
<script>
$(document).on('click', 'a', function(event) {
if($(this).data('hover') !== "Blog"){
event.preventDefault();
$('html, body').animate({
scrollTop: $( $.attr(this, 'href') ).offset().top
}, 500);
});
</script>
var doc = document;
var myList = doc.getElementsByClassName("snip1143")[0];
var myListItems = myList.children;
var isHash = false;
var href;
for (var i = 0; i < myListItems.length; i++) {
href = myListItems[i].firstChild.getAttribute('href');
isHash = href.includes("#");
if(!isHash){
myListItems[i].firstChild.addEventListener('click', function(evt) {
event.preventDefault();
});
myListItems[i].classList.add("strike");
}
}
.strike{
text-decoration: line-through;
}
<ul class="snip1143">
<li>Home</li>
<li>About</li>
<li>Work</li>
<li>Blog </li>
<li>Contact</li>
</ul>
Coded directly on SO, I hope I got it right:
$(document).on('click', 'a', function(e) {
if ($(this).attr('href').indexOf('#') !== -1)
e.preventDefault();
};

Wordpress Divi Theme - Anchor link opens tab toggle

I am trying to get anchor links to open up tabs on a specific page.
When I am on the page that the tabs are on, and I click on the anchor link, it correctly scrolls to the tab and opens it --- however, if I am on a different page than the tabs are on, the anchor link only goes to that page, it does not open the tab.
URL: http://elkodowntown.wpengine.com/
The Anchor links are under the OUR MEMBERS menu in the navigation.
JS:
jQuery(function($) {
$('.menu-item-179 a').on('click', function(event){
tabScroll('.et_pb_tab_0');
return false;
});
$('.menu-item-180 a').on('click', function(event){
tabScroll('.et_pb_tab_1');
return false;
});
$('.menu-item-181 a').on('click', function(event){
tabScroll('.et_pb_tab_2');
return false;
});
$('.menu-item-182 a').on('click', function(event){
tabScroll('.et_pb_tab_3');
return false;
});
$('.menu-item-183 a').on('click', function(event){
tabScroll('.et_pb_tab_4');
return false;
});
function tabscroll(target) {
$("html, body").animate({ scrollTop: $('#member-tabs').offset().top }, 1000);
setTimeout($('#member-tabs' + target + ' a').click(), 2000 );
}
$(function hash() {
var hash = window.location.hash.replace('#', "");
if (hash == '#shop') { tabscroll('.et_pb_tab_1'); }
if (hash == '#service') { tabscroll('.et_pb_tab_0'); }
if (hash == '#eat-drink') { tabscroll('.et_pb_tab_2'); }
if (hash == '#arts-entertainment') { tabscroll('.et_pb_tab_3'); }
if (hash == '#stay') { tabscroll('.et_pb_tab_4'); }
});
});
Anchor Links HTML:
<ul class="sub-menu">
<li id="menu-item-179" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-179">Shop</li>
<li id="menu-item-180" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-180">Service</li>
<li id="menu-item-181" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-181">Eat & Drink</li>
<li id="menu-item-182" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-182">Arts & Entertainment</li>
<li id="menu-item-183" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-183">Stay</li>
</ul>
Tabs HTML:
<div id="member-tabs" class="et_pb_module et_pb_tabs et_pb_tabs_0 et_slide_transition_to_3 et_slide_transition_to_0">
<ul class="et_pb_tabs_controls clearfix">
<li class="et_pb_tab_0 et_pb_tab_active">Shop</li><li class="et_pb_tab_1">Service</li><li class="et_pb_tab_2">Eat & Drink</li><li class="et_pb_tab_3">Arts & Entertainment</li><li class="et_pb_tab_4">Stay</li>
</ul>
The anchor links (#shop,#service, etc) are being called by <a name="#shop"> here (directly under the Tabs HTML):
<div class="et_pb_tab clearfix et_pb_active_content et_pb_tab_0 et-pb-active-slide" style="z-index: 1; display: block; opacity: 1;">
<a name="shop"></a><!--- tab content here --->
</div>
I'm sure there is a better way to organize my JS.
Any help is appreciated!
After looking through the code for a while, the problem finally dawned on me. You currently wrap each of the click handlers inside their own jQuery function:
jQuery(function($) {
$('.menu-item-183 a').on('click', function(event){
tabScroll();
return false;
});
function tabScroll(){
$('#member-tabs .et_pb_tab_4 a').click();
$("html, body").animate({ scrollTop: $('#member-tabs').offset().top }, 1000);
}
});
jQuery(function($) { ...
In each of these contexts, tabscroll() only has scope relative to the outer jQuery function. That is to say, in the above context, only menu-item-183 will have access to that particular tabscroll() function.
You later try to reference the tabscroll() function outside of that scope:
$(function hash() {
var hash = window.location.hash.replace('#', "");
if (hash == '#shop') { tabscroll(); }
if (hash == '#service') { tabscroll(); }
if (hash == '#eat-drink') { tabscroll(); }
if (hash == '#arts-entertainment') { tabscroll(); }
if (hash == '#stay') { tabscroll(); }
});
As this block reads, all conditionals are trying to do the exact same thing (call tabscroll() with no given parameter), and the condition could essentially be written as:
if (hash == '#shop' || hash == '#service' || ... ) {
tabscroll();
}
But you need the tabscroll function to redirect to different locations that aren't the same as hash, which means you have to manually separate them out:
if (hash == '#shop') { tabscroll('.et_pb_tab_1'); }
if (hash == '#service') { tabscroll('.et_pb_tab_0'); }
if (hash == '#eat-drink') { tabscroll('.et_pb_tab_2'); }
if (hash == '#arts-entertainment') { tabscroll('.et_pb_tab_3'); }
if (hash == '#stay') { tabscroll('.et_pb_tab_4'); }
Then simply change your tabscroll function to allow for this:
function tabscroll(target) {
$('#member-tabs' + target + ' a').click();
$("html, body").animate({ scrollTop: $('#member-tabs').offset().top }, 1000);
}
The final step is to make sure that this new tabscroll() function is accessible from your condition. With your current code structure, it should be placed just above or below $(function hash() {});
Ultimately you should restructure your code so that every click links to this new tabscroll() function, but this should be enough to solve the problem for now :)
Hope this helps! :)

jQuery: remember data-toggle tab when pagination

I have nav-tabs:
<ul class="nav nav-tabs">
<li class=""> 승인 대기 </li>
<li> 결제 대기 </li>
<li> 결제 완료 </li>
<li> 취소 완료 </li>
</ul>
and each tab has pagination.
This is my jQuery code for remembering last tab when pagination:
test.js
$(document).ready(function() {
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
// Execution1
localStorage.setItem('lastTab', $(this).attr('href'));
});
// Execution2
var lastTab = localStorage.getItem('lastTab');
if (lastTab) {
$('[href="' + lastTab + '"]').tab('show');
} else {
$('[href="#not-permitted"]').tab('show');
}
});
This works bad because Execution2 part should be executed after Execution1 executed, but it doesn't work sometime because event function is asynchronous.
So I changed the code like this:
$(document).ready(function() {
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
localStorage.setItem('lastTab', $(this).attr('href'));
// go to the latest tab, if it exists:
var lastTab = localStorage.getItem('lastTab');
if (lastTab) {
$('[href="' + lastTab + '"]').tab('show');
} else {
$('[href="#not-permitted"]').tab('show');
}
});
});
Seems good but it doesn't show any tab when page is loaded(or refresh) because shown.bs.tab event does not occur when page is firstly loaded.
Could you give me some idea, please?
Edit
$(document).ready(function() {
$('a[data-toggle="tab"]').trigger("click")
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
localStorage.setItem('lastTab', $(this).attr('href'));
// go to the latest tab, if it exists:
var lastTab = localStorage.getItem('lastTab');
if (lastTab) {
$('[href="' + lastTab + '"]').tab('show');
} else {
$('[href="#not-permitted"]').tab('show');
}
});
});
also doesn't work... it click all tabs one by one..continuously..

Removing class on one div when other is clicked

Following is my HTML,
<div class="container">
<ul class="navbar">
<li class="nb-link"><a>Home</a></li>
<li class="dropdown">
<a>CBSE</a>
<ul class="dropdown-menu">
<li>10th Standard</li>
<li>12th Standard</li>
</ul>
</li>
<li class="dropdown">
<a>Engineering</a>
<ul class="dropdown-menu">
<li>JEE - Main</li>
<li>JEE - Advanced</li>
</ul>
</li>
</ul>
I have 2 dropdowns . When I click one, it comes down. But when I click another, even that comes down without closing the previous one . This creates an overlap. The way I'm handling this using JS is as follows
$(document).ready(function() {
$('.dropdown').click(function() {
var $this = $(this);
if ($this.children('.dropdown-menu').hasClass('open')) {
$this.removeClass('active');
$('.navbar').$this.children('.dropdown-menu').removeClass('open');
$this.children('.dropdown-menu').fadeOut("fast");
}
else {
$this.addClass('active');
$this.children('.dropdown-menu').addClass('open');
$this.children('.dropdown-menu').fadeIn("fast");
}
});
});
How can I achieve a functionality using JS such that the previous dropdown closes when I click a new dropdown ? Also, the dropdowns should close when anywhere on the page is clicked ?
can try this
$(document).ready(function() {
$('.dropdown').click(function() {
var $this = $(this);
$('.dropdown').not($this).removeClass('active')
$('.dropdown-menu').not($this.find('.dropdown-menu')).removeClass('open');
$this.toggleClass('active');
$this.find('.dropdown-menu').toggleClass('open');
});
});
Working Demo
this is a function you can use if selectors is not target
// function for if selectors not target
function actionwindowclick(e , selector , action){
if (!$(selector).is(e.target) // if the target of the click isn't the container...
&& $(selector).has(e.target).length === 0) // ... nor a descendant of the container
{
action();
}
}
and you can use it in window click event like this
$(window).on('click', function(e){
actionwindowclick(e , ".dropdown , .dropdown-menu" , function(){
$('.dropdown').removeClass('active')
$('.dropdown-menu').removeClass('open');
});
});
Working Demo
Note: I think you may need to
event.stopPropagation()
while you trying to click on .dropdown-menu itself
$('.dropdown-menu').click(function(e) {
e.stopPropagation()
});
Try:
$(document).ready(function() {
$('.dropdown').click(function() {
var $this = $(this);
$this.children('.dropdown-menu').toggleClass('open');
if ($this.children('.dropdown-menu').hasClass('open')) {
$this.removeClass('active');
$this.children('.dropdown-menu').fadeOut("fast");
}
else {
$this.addClass('active');
$this.children('.dropdown-menu').fadeIn("fast");
}
});
});

Categories