Would like to use a basic hash router to drive navigation of bootstrap 4.6 tab component.
However when I call the .tab('show') function, the right tab toggles but it's respective tab-pane section does not get toggled. I made sure the tab-panes id attribute has the same value as the tabs href attribute.
I was able to make it work by manually showing and hiding the tab panes. But bootstrap has this functionality built in. Does anyone know how to do it ?
Thanks
hashRouteInit = function(callback) {
window.addEventListener('hashchange', callback, false);
}
const routes = {
'#/units': function() {
console.log('units');
},
'#/clients': function() {
console.log('clients');
},
'#/searches': function() {
console.log('searches');
},
};
hashRouteInit(function() {
console.log(window.location.hash);
console.log(routes);
if (routes[window.location.hash] != undefined) {
/*how can i remove the following 3 lines and let .tab('show') show the tab pane*/
/*$(`.tab-content .show`).hide();
$(`.tab-content .show`).removeClass('show');
$(`.tab-content .show`).removeClass('active');*/
$(`#stats-tabs a[href="${window.location.hash}"]`).tab('show');
/*how can i remove the following 3 lines and let .tab('show') show the tab pane*/
/*$(`.tab-content .tab-pane[id="${window.location.hash}"]`).addClass('show');
$(`.tab-content .tab-pane[id="${window.location.hash}"]`).addClass('active');
$(`.tab-content .tab-pane[id="${window.location.hash}"]`).show();*/
routes[window.location.hash]();
}
});
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="container">
<ul class="nav nav-tabs" id="stats-tabs" role="tablist">
<li class="nav-item" role="presentation"><a class="nav-link active" id="units-tab" href="#/units" role="tab" aria-controls="units" aria-selected="true">Units</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" id="clients-tab" href="#/clients" role="tab" aria-controls="clients" aria-selected="false">Clients</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" id="searches-tab" href="#/searches" role="tab" aria-controls="searches" aria-selected="false">Searches</a></li>
</ul>
<div class="tab-content pt-2" id="stats-tabs-content">
<div class="tab-pane fade show active" id="#/units" role="tabpanel" aria-labelledby="units-tab">units</div>
<div class="tab-pane fade" id="#/clients" role="tabpanel" aria-labelledby="clients-tab">clients</div>
<div class="tab-pane fade" id="#/searches" role="tabpanel" aria-labelledby="searches-tab">
<div id="search-overview-searches">searches</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.0/js/bootstrap.min.js"></script>
</body>
Apparently the HTML ID attribute has to start with a letter(https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id)
Once I set the href attributes to #name and used the same value but without the number sign for the ID of the tab pane. It started working.
Note that the spec(https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#:~:text=The%20id%20attribute%20specifies%20its,not%20contain%20any%20space%20characters.) doesn't say anything about not using slashes to construct a hierarchy in the id string. However if i want to have another tab section as a child in a tab pane, i won't be able to have an id like this(parent/child) and have bootstrap tabs work. So you are only left with - or _ which doesn't seem so intuitive in the URI. Especially once you wan't to add an numerical identifier onto it. Like so parent/child/3. Can't do that, but the spec doesn't say anything about not allowing slashes.
Does anyone know why forward slashes are not allowed in the id string if the first char is not a forward slash?
Related
I'm trying to add a Bootstrap tab panel goes like this:
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#tabs-1" role="tab">First Panel</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tabs-2" role="tab">Second Panel</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tabs-3" role="tab">Third Panel</a>
</li>
</ul><!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane active" id="tabs-1" role="tabpanel">
<p>First Panel</p>
</div>
<div class="tab-pane" id="tabs-2" role="tabpanel">
<p>Second Panel</p>
</div>
<div class="tab-pane" id="tabs-3" role="tabpanel">
<p>Third Panel</p>
</div>
</div>
Now I need to give link to users to see the panes like this:
https://sitename.com/page#tabs-2
But this won't work because the tab-pane with an id of tabs-2 does not have the .active class.
However, if I try loading https://sitename.com/page#tabs-1 The page properly redirects me to tab-pane with an id of tabs-1 (because it has .active class by default)
So how can I redirect users to different tab panes correctly?
You don't really need to check the fragment to switch between those tabs.
1) Import jQuery from here or:
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
2) Add this part to your code.
<script>
$(document).ready(function () {
$('.nav-tabs a').click(function () {
$(this).tab('show');
});
});
</script>
I already started answering your old question before you deleted it, but here is it again.
I didn't understood what you were trying to achieve, so I just looked into the code and made my version, its not the best but it works.
This is an onClick event handler, it gets executed on a click in your nav and changes the active classes.
// onClick event handler, gets executed on click
$(".nav-link").on("click", (e) => {
// store clicked element
const listItem = e.target;
// get hash
const hash = e.target.hash;
// remove all active classes
$(".nav-link, .tab-pane").removeClass("active");
// add active class to list item and tab panes
$(listItem).add(hash).addClass("active");
});
This part gets executed when you reload your page. You need to change your HTML for this to work, so remove the active class from nav-link and give every link an additional class (tabs-1, tabs-2 and tabs-3).
// when page is reloaded
$(document).ready(() => {
// get current hash
const hashList = window.location.hash;
const hashItems = hashList.slice(1);
// remove all active classes
$(".nav-link, .tab-pane").removeClass("active");
// add active class to nav-link and pane
$(hashList).add(`.${hashItems}`).addClass("active");
});
Both snippets need to be included in your script tag of course, also you need to import jQuery, if not already happened.
I have a service page that using bootstrap 4's pills .nav-pills navigation (this is not the main navigation navbar), which is working very well. My challenge is that i want to be able to click on a link on the home page that should open the targeted tab-panel on the service page. Haven't been able to find a way for almost a week now. How can i achieve this?
Service.html
<div class="nav flex-column nav-pills col-md-3" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<ul class="list-group list-unstyled">
<li class="nav-item">
<a class="nav-link list-group-item" id="v-pills-manpower-tab" data-toggle="pill" href="#v-pills-manpower" role="tab" aria-controls="v-pills-manpower" aria-selected="false">Manpower Supply</a>
</li>
</ul>
</div>
<div class="tab-content col-md-8" id="v-pills-tabContent">
<div class="tab-pane fade" id="v-pills-manpower" role="tabpanel" aria-labelledby="v-pills-manpower-tab">
<h5>Man Power Supply</h5>
</div>
Home.html
<a href="services.html#v-pills-manpower" data-toggle="tab" >
My code in home.html doesn't work but that's one of my many attempts.
On the home page, configure data attributes to help. I've added data-tab-name to the anchor and it defines the desired, selected tab for the service page.
When the page loads, it re-configures the onclick of the link so that the tab name can be stored in localStorage before redirecting the user to the service page.
Home.html
<a href="services.html" data-tab-name="v-pills-manpower" data-toggle="tab" >
<script type="text/javascript">
window.onload = function() {
document.querySelectorAll('[data-toggle="tab"]').forEach(function(item, index){
item.addEventListener('click', function(e){
e.preventDefault();
localStorage.selectedTabName = item.getAttribute('data-tab-name');
window.location.href = item.href;
});
});
};
</script>
When the service page loads, the javascript looks for the saved tab name in localStorage, identifies that tab and then makes it the active tab by applying the "active" class to the appropriate element.
Service.html
<script type="text/javascript">
window.onload = function() {
document.querySelectorAll('.nav-link').forEach(function(item, index){
var isActive = (item.className.indexOf('active')>-1);
if (item.id==localStorage.selectedTabName) {
if (!isActive) {
item.className += ' active';
}
item.setAttribute('aria-selected', 'true');
} else {
item.setAttribute('aria-selected', 'false');
if (isActive) {
item.className = item.className.replace('active', '');
}
}
});
};
</script>
I have the following tab structure in the form of a form with a submit button on the second tab. Is it possible for the tabs to auto-change upon a certain condition?
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#home">Home</a></li>
<li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
<li><a data-toggle="tab" href="#menu2">Menu 2</a></li>
</ul>
<div class="tab-content">
<div id="home" class="tab-pane fade in active">
<h3>HOME</h3>
<p>Some content.</p>
</div>
<div id="menu1" class="tab-pane fade">
<h3>Menu 1</h3>
<p>Some content in menu 1.</p>
</div>
<div id="menu2" class="tab-pane fade">
<h3>Menu 2</h3>
<p>Some content in menu 2.</p>
</div>
</div>
It's pretty hard to answer this without knowing what condition you want or seeing any code apart from the HTML structure (and without any CSS).
I'm assuming clicking on the anchors will change tabs, so what you need to do is add ids to them:
<li><a data-toggle="tab" href="#menu1" id="tab1">Menu 1</a></li>
<li><a data-toggle="tab" href="#menu2" id="tab2">Menu 2</a></li>
and then if you're using jQuery do something like:
if(/*whatever condition you want*/){
$('#tab2').click();
}
otherwise:
if(/*whatever condition you want*/){
document.getElementById('tab2').click();
}
What you're looking for is called a multi-step form or a form wizard.
There are multiple examples on google on how to achieve such a solution and many many many JavaScript and jQuery modules/libraries which provide such functionality.
one sample can be found at this JSFiddle by JQ Purfect using bootstrap wizard:
http://jsfiddle.net/JQPurfect/nGnbJ/2/
$(document).ready(function () {
$('#rootwizard').bootstrapWizard({
onTabShow: function (tab, navigation, index) {
var $total = navigation.find('li').length;
var $current = index + 1;
var $percent = ($current / $total) * 100;
$('.bar').text($percent.toFixed(0) + '%');
$('#rootwizard').find('.bar').css({
width: $percent + '%'
});
}
});
window.prettyPrint && prettyPrint()
});
Or follow this one: https://www.npmjs.com/package/jquery-simple-wizard
You can use the bootstrap tabs javascript reference to manipulate tabs to do something based on a condition. You can see the javascript reference at http://www.w3schools.com/bootstrap/bootstrap_ref_js_tab.asp. If you are trying to show your tab then you should be able to just use something like the following:
$('.nav-tabs a[href="#menu2"]').tab('show')
Not knowing what condition you want to toggle the tab on I made a fiddle to show you with just a click function but you can use whatever fucntion you want to show the tab.
Here is a fiddle Fiddle
In my page i use bootstrap's tab, but when i click each of tab, content of tab doesn't show correctly, this is my code:
<div class="w470px exam" style="border: 1px solid #ddd; margin-top: 30px;">
<ul id="myTab" class="nav nav-tabs nav-justified">
<li class="active">Home</li>
<li>Favoriets</li>
<li>Friends</li>
<li>Experience</li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade in active" id="tab-home">
HOME
</div>
<div class="tab-pane fade active" id="tab-fav">
My favoriets
</div>
<div class="tab-pane fade active" id="tab-fr">
My Friends
</div>
<div class="tab-pane fade active" id="tab-ex">
My experience
</div>
</div>
<script type="text/javascript">
$(function () {
var navTabs = $('.nav-tabs a');
var hash = window.location.hash;
hash && navTabs.filter('[data-value="' + hash + '"]').tab('show');
navTabs.on('shown', function (e) {
var newhash = $(e.target).attr('data-value');
window.location.hash = newhash;
});
})
</script>
</div>
JSFIDDLE
Where am i wrong? How can i fix it?
You have active class on all tab-pane divs. Remove it from all of them but the first one. BTW, in bootstrap 3, the event it is not show, it is shown.bs.tab Bootstrap 3 tabs.
I personally use this code: Twitter Bootstrap Tabs: Go to Specific Tab on Page Reload or Hyperlink, the only change I made, was to replace the on('show' with on('shown.bs.tab' .
On your JSFiddle a reference to the jQuery library is missing. Once adding a jQuery reference under Frameworks & Extensions it's switching tab content.
Under the Bootstrap documentation is states that jQuery is required for bootstrap javascript features: http://getbootstrap.com/getting-started/#whats-included
Also, your function is being using jQuery notation.
I have a pie chart. Functionality is that when I select a particular section of pie chart, then it redirects to the next page with selected tab. I am able to get value of that pie chart section by using this code:
var search = document.URL.split('?')[1];
Now my fight is how to enable particular tab on the next page on the basis of value of "search" variable.
Next when user comes direct to this page then 1st tab is enable by default. for this I used the code:
<div class="tab-pane in active" id="tab1">
I have tried in many ways(like $("ul.tabs li:first").addClass("active").show() or using eq()) but have no success. Please let me know if anyone can help me out.
This should do the job:
<script>
$(function() {
$("#tabs").tabs();
var search = document.URL.split('?')[1];
switch (search) {
case "error":
$("#tab1 > a").click();
break;
case "suspect":
$("#tab2 > a").click();
break;
}
});
</script>
<div id="tabs">
<ul class="nav nav-tabs" id="myTab">
<li id="tab1" class="active"> Error</li>
<li id="tab2"><a href="#suspect" data-toggle="tab" >Suspect </a></li>
</ul>
<div class="tab-pane in active" id="error">
Error
</div>
<div class="tab-pane" id="suspect">
Suspect
</div>
</div>