Related
I'm developing a web page in which I'm using Twitter's Bootstrap Framework and their Bootstrap Tabs JS. It works great except for a few minor issues, one of which is I do not know how go directly to a specific tab from an external link. For example:
Home
Notes
should go to the Home tab and the Notes tab respectively when clicked on the links from an external page
Here is my solution to the problem, a bit late perhaps. But it could maybe help others:
// Javascript to enable link to tab
var hash = location.hash.replace(/^#/, ''); // ^ means starting, meaning only match the first hash
if (hash) {
$('.nav-tabs a[href="#' + hash + '"]').tab('show');
}
// Change hash for page-reload
$('.nav-tabs a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash;
})
UPDATE
For Bootstrap 3, change .on('shown', ...) to .on('shown.bs.tab', ....)
This is based off of #dubbe answer and this SO accepted answer. It handles the issue with window.scrollTo(0,0) not working correctly. The problem is that when you replace the url hash on tab shown, the browser will scroll to that hash since its an element on the page. To get around this, add a prefix so the hash doesn't reference an actual page element
// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
$('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
}
// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
Example of use
If you have tab-pane with id="mytab" you need to put your link like this:
Go to Specific Tab
you could trigger a click event on the corresponding tab link:
$(document).ready(function(){
if(window.location.hash != "") {
$('a[href="' + window.location.hash + '"]').click()
}
});
This is an improved implementation of dubbe's solution which prevent scrolling.
// Javascript to enable link to tab
var url = document.location.toString();
if (url.match('#')) {
$('.nav-tabs a[href="#'+url.split('#')[1]+'"]').tab('show') ;
}
// With HTML5 history API, we can easily prevent scrolling!
$('.nav-tabs a').on('shown.bs.tab', function (e) {
if(history.pushState) {
history.pushState(null, null, e.target.hash);
} else {
window.location.hash = e.target.hash; //Polyfill for old browsers
}
})
While the JavaScript solution provided may work, I went a slightly different way that requires no additional JavaScript, but does require logic in your view. You create a link with a standard URL parameter, like:
My Link
Then you simply detect the value of activeTab to write 'class="active"' in the appropriate <li>
Pseudocode (implement accordingly in your language). Note I've set 'home' tab as a default active if no parameter provided in this example.
$activetabhome = (params.activeTab is null or params.activeTab == 'home') ? 'class="active"' : '';
$activetabprofile = (params.activeTab == 'profile') ? 'class="active"' : '';
<li $activetabhome>Home</li>
<li $activetabprofile>Profile</li>
I am not a big fan of if...else; so I took a simpler approach.
$(document).ready(function(event) {
$('ul.nav.nav-tabs a:first').tab('show'); // Select first tab
$('ul.nav.nav-tabs a[href="'+ window.location.hash+ '"]').tab('show'); // Select tab by name if provided in location hash
$('ul.nav.nav-tabs a[data-toggle="tab"]').on('shown', function (event) { // Update the location hash to current tab
window.location.hash= event.target.hash;
})
});
Pick a default tab (usually the first)
Switch to tab (if such an element is indeed present; let jQuery handle it); Nothing happens if a wrong hash is specified
[Optional] Update the hash if another tab is manually chosen
Doesn't address scrolling to requested hash; but should it?
For Bootstrap 3:
$('.nav-tabs a[href="#' + tabID + '"]').tab('show');
https://jsfiddle.net/DTcHh/6638/
This works in Bootstrap 3 and improves dubbe and flynfish 's 2 top answers by integrating GarciaWebDev 's answer as well (which allows for url parameters after the hash and is straight from Bootstrap authors on the github issue tracker):
// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
hash = hash.replace(prefix,'');
var hashPieces = hash.split('?');
activeTab = $('.nav-tabs a[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');
}
// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
Building on Demircan Celebi's solution; I wanted the tab to open when modifying the url and open tab without having to reload the page from the server.
<script type="text/javascript">
$(function() {
openTabHash(); // for the initial page load
window.addEventListener("hashchange", openTabHash, false); // for later changes to url
});
function openTabHash()
{
console.log('openTabHash');
// Javascript to enable link to tab
var url = document.location.toString();
if (url.match('#')) {
$('.nav-tabs a[href="#'+url.split('#')[1]+'"]').tab('show') ;
}
// With HTML5 history API, we can easily prevent scrolling!
$('.nav-tabs a').on('shown.bs.tab', function (e) {
if(history.pushState) {
history.pushState(null, null, e.target.hash);
} else {
window.location.hash = e.target.hash; //Polyfill for old browsers
}
})
}
</script>
Just insert this code on your page:
$(function(){
var hash = window.location.hash;
hash && $('ul.nav a[href="' + hash + '"]').tab('show');
$('.nav-tabs a').click(function (e) {
$(this).tab('show');
var scrollmem = $('body').scrollTop();
window.location.hash = this.hash;
$('html,body').scrollTop(scrollmem);
});
});
This code selects the right tab depending on the #hash and adds the right #hash when a tab is clicked. (this uses jquery)
In Coffeescript :
$(document).ready ->
if location.hash != ''
$('a[href="'+location.hash+'"]').tab('show')
$('a[data-toggle="tab"]').on 'shown', (e) ->
location.hash = $(e.target).attr('href').substr(1)
or in JS :
$(document).ready(function() {
if (location.hash !== '') $('a[href="' + location.hash + '"]').tab('show');
return $('a[data-toggle="tab"]').on('shown', function(e) {
return location.hash = $(e.target).attr('href').substr(1);
});
});
$(function(){
var hash = window.location.hash;
hash && $('ul.nav a[href="' + hash + '"]').tab('show');
});
This code from http://github.com/twitter/bootstrap/issues/2415#issuecomment-4450768 worked for me perfectly.
#flynfish + #Ztyx solution that I use for nested tabs:
handleTabLinks();
function handleTabLinks() {
if(window.location.hash == '') {
window.location.hash = window.location.hash + '#_';
}
var hash = window.location.hash.split('#')[1];
var prefix = '_';
var hpieces = hash.split('/');
for (var i=0;i<hpieces.length;i++) {
var domelid = hpieces[i].replace(prefix,'');
var domitem = $('a[href=#' + domelid + '][data-toggle=tab]');
if (domitem.length > 0) {
domitem.tab('show');
}
}
$('a[data-toggle=tab]').on('shown', function (e) {
if ($(this).hasClass('nested')) {
var nested = window.location.hash.split('/');
window.location.hash = nested[0] + '/' + e.target.hash.split('#')[1];
} else {
window.location.hash = e.target.hash.replace('#', '#' + prefix);
}
});
}
childrens should have class="nested"
I came up with a solution that uses the url hash or localStorage depending on the availability of the latter with below code:
$(function(){
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
localStorage.setItem('activeTab', $(e.target).attr('href'));
})
var hash = window.location.hash;
var activeTab = localStorage.getItem('activeTab');
if(hash){
$('#project-tabs a[href="' + hash + '"]').tab('show');
}else if (activeTab){
$('#project-tabs a[href="' + activeTab + '"]').tab('show');
}
});
I would suggest you use the code provided by Bootstrap authors on their issue tracker on GitHub:
var hash = location.hash
, hashPieces = hash.split('?')
, activeTab = $('[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');
You can find on the link to the issue more information about why they didn't choose to support that.
Tried couple of ways discussed above and end up with following working solution, just copy and paste in your editor to try. To test just change hash to inbox, outbox, compose in url and hit enter key.
<html>
<head>
<link type='text/css' rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css' />
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container body-content">
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#inbox">Inbox</a></li>
<li><a data-toggle="tab" href="#outbox">Outbox</a></li>
<li><a data-toggle="tab" href="#compose">Compose</a></li>
</ul>
<div class="tab-content">
<div id="inbox" class="tab-pane fade in active">
Inbox Content
</div>
<div id="outbox" class="tab-pane fade">
Outbox Content
</div>
<div id="compose" class="tab-pane fade">
Compose Content
</div>
</div>
</div>
<script>
$(function () {
var hash = window.location.hash;
hash && $('ul.nav a[href="' + hash + '"]').tab('show');
});
</script>
</body>
</html>
Hope this will save your time.
Here is what i did, really simple, and provided your tab links have an ID associated with them you can get the href attribute and pass that over to the function that shows the tab contents:
<script type="text/javascript">
jQuery(document).ready(function() {
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
var tab = jQuery(hash.replace(prefix,"")).attr('href');
jQuery('.nav-tabs a[href='+tab+']').tab('show');
}
});
</script>
Then in your url you can add the hash as something like: #tab_tab1, the 'tab_' part is removed from the hash itself so the ID of the actual tab link in the nav-tabs (tabid1) is placed after this, so your url would look something like: www.mydomain.com/index.php#tab_tabid1.
This works perfect for me and hope it helps someone else :-)
If it matters to anybody, the following code is small and works flawless, to get a single hash value from the URL and show that:
<script>
window.onload = function () {
let url = document.location.toString();
let splitHash = url.split("#");
if (splitHash[1]) {document.getElementById(splitHash[1]).click();}
};
</script>
what it does is it retrieves the id and fires the click event. Simple.
I just had this issue, but needed to handle multiple tab levels. The code is rather ugly (see comments), but does its job: https://gist.github.com/JensRantil/4721860 Hopefully someone else will find it useful (and feel free to propose better solutions!).
This is my solution to handle nested tabs.
I just added a function to check if the active tab has a parent tab to be activated.
This is the function:
function activateParentTab(tab) {
$('.tab-pane').each(function() {
var cur_tab = $(this);
if ( $(this).find('#' + tab).length > 0 ) {
$('.nav-tabs a[href=#'+ cur_tab.attr('id') +']').tab('show');
return false;
}
});
}
And can be called like this (Based on #flynfish's solution):
var hash = document.location.hash;
var prefix = "";
if (hash) {
$('.nav-tabs a[href='+hash.replace(prefix,"")+']').tab('show');
activateParentTab(hash);
}
// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
This solution works pretty fine to me at the moment.
Hope this can be useful for someone else ;)
I had to modify some bits for this to work for me.
I am using Bootstrap 3 and jQuery 2
// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "!";
if (hash) {
hash = hash.replace(prefix,'');
var hashPieces = hash.split('?');
activeTab = $('[role="tablist"] a[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');
}
// Change hash for page-reload
$('[role="tablist"] a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
Combining peices from other answers, here is a solution that can open many levels of nested tabs:
// opens all tabs down to the specified tab
var hash = location.hash.split('?')[0];
if(hash) {
var $link = $('[href=' + hash + ']');
var parents = $link.parents('.tab-pane').get();
$(parents.reverse()).each(function() {
$('[href=#' + this.id + ']').tab('show') ;
});
$link.tab('show');
}
For Bootstrap 5.1 for redirecting to specific tab
var hash = location.hash.replace(/^#/, '');
if (hash) {
var someVarName = $('.nav-tabs a[href="#' + hash + '"]');
var tab = new bootstrap.Tab(someVarName);
tab.show();
}
Change hash for page-reload
$('.nav-tabs a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash;
window.scrollTo(0, 0);
})
I make sth like this for links with ajax #!# (e.g./test.com#!#test3) but you can modify it whatever you like
$(document).ready(function() {
let hash = document.location.hash;
let prefix = "!#";
//change hash url on page reload
if (hash) {
$('.nav-tabs a[href=\"'+hash.replace(prefix,"")+'\"]').tab('show');
}
// change hash url on switch tab
$('.nav-tabs a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
});
Example with simple page on Github here
I know this thread is very old, but I'll leave here my own implementation:
$(function () {
// some initialization code
addTabBehavior()
})
// Initialize events and change tab on first page load.
function addTabBehavior() {
$('.nav-tabs a').on('show.bs.tab', e => {
window.location.hash = e.target.hash.replace('nav-', '')
})
$(window).on('popstate', e => {
changeTab()
})
changeTab()
}
// Change the current tab and URL hash; if don't have any hash
// in URL, so activate the first tab and update the URL hash.
function changeTab() {
const hash = getUrlHash()
if (hash) {
$(`.nav-tabs a[href="#nav-${hash}"]`).tab('show')
} else {
$('.nav-tabs a').first().tab('show')
}
}
// Get the hash from URL. Ex: www.example.com/#tab1
function getUrlHash() {
return window.location.hash.slice(1)
}
Note that I'm using a nav- class prefix to nav links.
Building on Peter's answer, and incorporating https://stackoverflow.com/a/901144/1604205, here's the code in JS:
<script>
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
$activetabhome = (params.activeTab === null || params.activeTab == 'home') ? 'class="active"' : '';
$activetabprofile = (params.activeTab == 'profile') ? 'class="active"' : '';
</script>
<li $activetabhome>Home</li>
<li $activetabprofile>Profile</li>
Hi I have a page that navigates using anchors. On load the index page (A) needs to jump to anchor. Fine I can do this with on load function but coming back to the page A from page B I want to jump to a different anchor. I have this working:
<!-- go to Anchor -->
<script type="text/javascript">
function goToAnchor() {
var urllocation = location.href;
if(urllocation.indexOf("#top") > -1){
window.location.hash="top";
} else {
window.location.hash="middle";
}
}
</script>
#middle is the anchor to use when coming from a link that contains no anchor (or from typing the address into the url bar). I want to add three more 'if's'. I am fairly new at js so bear with me if I am doing something silly. I tried this:
function goToAnchor() {
var urllocation = location.href;
if(urllocation.indexOf("#right") > -1){
window.location.hash="right";
} else {
window.location.hash="middle";
}
if(urllocation.indexOf("#bottom") > -1){
window.location.hash="bottom";
} else {
window.location.hash="middle";
}
if(urllocation.indexOf("#left") > -1){
window.location.hash="left";
} else {
window.location.hash="middle";
}
But not joy, the js breaks and no longer goes to #middle on page load.
I tried a wild card approach:
function goToAnchor() {
var urllocation = location.href;
if(urllocation.indexOf("#.") > -1){
window.location.hash=".";
} else {
window.location.hash="middle";
}
}
Again, no joy.
Any help please.. thanks kindly
I am not quite sure I understand the effect you are trying to achieve (since window.location.hash should already contain the hash part of your url), but your code should probably rather be
function goToAnchor() {
var urllocation = location.href;
if (urllocation.indexOf("#right") > -1) {
window.location.hash = "right";
} else if (urllocation.indexOf("#bottom") > -1) {
window.location.hash = "bottom";
} else if(urllocation.indexOf("#left") > -1) {
window.location.hash = "left";
} else {
window.location.hash = "middle";
}
}
I am also guessing that your 'wild card' approach is meant to use regular expressions:
function goToAnchor() {
var urllocation = location.href;
var hashMatch = urllocation.match(/#(.*)/)
if (hashMatch){
window.location.hash = hashMatch[1];
} else {
window.location.hash = "middle";
}
}
Again, I don't quite see what effect this code should have, since window.location.hash will probably have the same value before and after the assignment.
If you just want to go back to the hash in the URL, have you tried something like this?
var hash = window.location.hash || "middle"; //Get current hash or default to "middle" if no hash is currently set
window.location.hash = +new Date() + ""; //Remove the hash and set it to some random value
window.location.hash = hash; //Set to the old hash
I'm trying to remove a landing page when I click on a link on a page. The page isn't mine so I'm trying to change the href with a user script.
Without any modification, the link looks like this:
https://www.domain.com/out.php?u=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DPUZ1bC-1XjA%26amp%3Bfeature%3Drelated
What I want:
http://www.youtube.com/watch?v=PUZ1bC-1XjA&feature=related
What I got so far:
http://www.youtube.com%2fwatch%3fv%3dpuz1bc-1xja%26amp%3bfeature%3drelated/
But that adress doesn't work in the browser.
This is my current code:
$('a').each(function(index) {
var aLink = $(this).attr('href');
if(aLink) {
if(aLink.indexOf("out.php?u=") > 0) {
aLink = aLink.substring(51);
console.log(aLink);
$(this).attr('href', "http://"+aLink);
console.log($(this).prop('href'));
}
}
});
All help and tips are appreciated.
You need to decode the URL using decodeURIComponent
Change:
$(this).attr('href', "http://"+aLink);
To:
$(this).attr('href', 'http://' + decodeURIComponent(aLink));
Take a look at decodeURIComponent
You can also make use of the hostname, pathname, and search parameters of anchor elements.
// general function to turn query strings into objects
function deserialize_query_string(qs) {
var params = {};
var fields = qs.split('&');
var field;
for (var i=0; i<fields.length; i++) {
field = fields[i].split('=');
field[0] = decodeURIComponent(field[0]);
field[1] = decodeURIComponent(field[1]);
params[field[0]] = field[1];
}
return params;
}
$(document.links).each(function(i){
if (this.hostname=='www.domain.com' && this.pathname=='/out.php') {
var params = deserialize_query_string(this.search);
if (params.u) {
this.href = u;
}
}
});
I'm developing a web page in which I'm using Twitter's Bootstrap Framework and their Bootstrap Tabs JS. It works great except for a few minor issues, one of which is I do not know how go directly to a specific tab from an external link. For example:
Home
Notes
should go to the Home tab and the Notes tab respectively when clicked on the links from an external page
Here is my solution to the problem, a bit late perhaps. But it could maybe help others:
// Javascript to enable link to tab
var hash = location.hash.replace(/^#/, ''); // ^ means starting, meaning only match the first hash
if (hash) {
$('.nav-tabs a[href="#' + hash + '"]').tab('show');
}
// Change hash for page-reload
$('.nav-tabs a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash;
})
UPDATE
For Bootstrap 3, change .on('shown', ...) to .on('shown.bs.tab', ....)
This is based off of #dubbe answer and this SO accepted answer. It handles the issue with window.scrollTo(0,0) not working correctly. The problem is that when you replace the url hash on tab shown, the browser will scroll to that hash since its an element on the page. To get around this, add a prefix so the hash doesn't reference an actual page element
// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
$('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
}
// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
Example of use
If you have tab-pane with id="mytab" you need to put your link like this:
Go to Specific Tab
you could trigger a click event on the corresponding tab link:
$(document).ready(function(){
if(window.location.hash != "") {
$('a[href="' + window.location.hash + '"]').click()
}
});
This is an improved implementation of dubbe's solution which prevent scrolling.
// Javascript to enable link to tab
var url = document.location.toString();
if (url.match('#')) {
$('.nav-tabs a[href="#'+url.split('#')[1]+'"]').tab('show') ;
}
// With HTML5 history API, we can easily prevent scrolling!
$('.nav-tabs a').on('shown.bs.tab', function (e) {
if(history.pushState) {
history.pushState(null, null, e.target.hash);
} else {
window.location.hash = e.target.hash; //Polyfill for old browsers
}
})
While the JavaScript solution provided may work, I went a slightly different way that requires no additional JavaScript, but does require logic in your view. You create a link with a standard URL parameter, like:
My Link
Then you simply detect the value of activeTab to write 'class="active"' in the appropriate <li>
Pseudocode (implement accordingly in your language). Note I've set 'home' tab as a default active if no parameter provided in this example.
$activetabhome = (params.activeTab is null or params.activeTab == 'home') ? 'class="active"' : '';
$activetabprofile = (params.activeTab == 'profile') ? 'class="active"' : '';
<li $activetabhome>Home</li>
<li $activetabprofile>Profile</li>
I am not a big fan of if...else; so I took a simpler approach.
$(document).ready(function(event) {
$('ul.nav.nav-tabs a:first').tab('show'); // Select first tab
$('ul.nav.nav-tabs a[href="'+ window.location.hash+ '"]').tab('show'); // Select tab by name if provided in location hash
$('ul.nav.nav-tabs a[data-toggle="tab"]').on('shown', function (event) { // Update the location hash to current tab
window.location.hash= event.target.hash;
})
});
Pick a default tab (usually the first)
Switch to tab (if such an element is indeed present; let jQuery handle it); Nothing happens if a wrong hash is specified
[Optional] Update the hash if another tab is manually chosen
Doesn't address scrolling to requested hash; but should it?
For Bootstrap 3:
$('.nav-tabs a[href="#' + tabID + '"]').tab('show');
https://jsfiddle.net/DTcHh/6638/
This works in Bootstrap 3 and improves dubbe and flynfish 's 2 top answers by integrating GarciaWebDev 's answer as well (which allows for url parameters after the hash and is straight from Bootstrap authors on the github issue tracker):
// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
hash = hash.replace(prefix,'');
var hashPieces = hash.split('?');
activeTab = $('.nav-tabs a[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');
}
// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
Building on Demircan Celebi's solution; I wanted the tab to open when modifying the url and open tab without having to reload the page from the server.
<script type="text/javascript">
$(function() {
openTabHash(); // for the initial page load
window.addEventListener("hashchange", openTabHash, false); // for later changes to url
});
function openTabHash()
{
console.log('openTabHash');
// Javascript to enable link to tab
var url = document.location.toString();
if (url.match('#')) {
$('.nav-tabs a[href="#'+url.split('#')[1]+'"]').tab('show') ;
}
// With HTML5 history API, we can easily prevent scrolling!
$('.nav-tabs a').on('shown.bs.tab', function (e) {
if(history.pushState) {
history.pushState(null, null, e.target.hash);
} else {
window.location.hash = e.target.hash; //Polyfill for old browsers
}
})
}
</script>
Just insert this code on your page:
$(function(){
var hash = window.location.hash;
hash && $('ul.nav a[href="' + hash + '"]').tab('show');
$('.nav-tabs a').click(function (e) {
$(this).tab('show');
var scrollmem = $('body').scrollTop();
window.location.hash = this.hash;
$('html,body').scrollTop(scrollmem);
});
});
This code selects the right tab depending on the #hash and adds the right #hash when a tab is clicked. (this uses jquery)
In Coffeescript :
$(document).ready ->
if location.hash != ''
$('a[href="'+location.hash+'"]').tab('show')
$('a[data-toggle="tab"]').on 'shown', (e) ->
location.hash = $(e.target).attr('href').substr(1)
or in JS :
$(document).ready(function() {
if (location.hash !== '') $('a[href="' + location.hash + '"]').tab('show');
return $('a[data-toggle="tab"]').on('shown', function(e) {
return location.hash = $(e.target).attr('href').substr(1);
});
});
$(function(){
var hash = window.location.hash;
hash && $('ul.nav a[href="' + hash + '"]').tab('show');
});
This code from http://github.com/twitter/bootstrap/issues/2415#issuecomment-4450768 worked for me perfectly.
#flynfish + #Ztyx solution that I use for nested tabs:
handleTabLinks();
function handleTabLinks() {
if(window.location.hash == '') {
window.location.hash = window.location.hash + '#_';
}
var hash = window.location.hash.split('#')[1];
var prefix = '_';
var hpieces = hash.split('/');
for (var i=0;i<hpieces.length;i++) {
var domelid = hpieces[i].replace(prefix,'');
var domitem = $('a[href=#' + domelid + '][data-toggle=tab]');
if (domitem.length > 0) {
domitem.tab('show');
}
}
$('a[data-toggle=tab]').on('shown', function (e) {
if ($(this).hasClass('nested')) {
var nested = window.location.hash.split('/');
window.location.hash = nested[0] + '/' + e.target.hash.split('#')[1];
} else {
window.location.hash = e.target.hash.replace('#', '#' + prefix);
}
});
}
childrens should have class="nested"
I came up with a solution that uses the url hash or localStorage depending on the availability of the latter with below code:
$(function(){
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
localStorage.setItem('activeTab', $(e.target).attr('href'));
})
var hash = window.location.hash;
var activeTab = localStorage.getItem('activeTab');
if(hash){
$('#project-tabs a[href="' + hash + '"]').tab('show');
}else if (activeTab){
$('#project-tabs a[href="' + activeTab + '"]').tab('show');
}
});
I would suggest you use the code provided by Bootstrap authors on their issue tracker on GitHub:
var hash = location.hash
, hashPieces = hash.split('?')
, activeTab = $('[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');
You can find on the link to the issue more information about why they didn't choose to support that.
Tried couple of ways discussed above and end up with following working solution, just copy and paste in your editor to try. To test just change hash to inbox, outbox, compose in url and hit enter key.
<html>
<head>
<link type='text/css' rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css' />
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container body-content">
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#inbox">Inbox</a></li>
<li><a data-toggle="tab" href="#outbox">Outbox</a></li>
<li><a data-toggle="tab" href="#compose">Compose</a></li>
</ul>
<div class="tab-content">
<div id="inbox" class="tab-pane fade in active">
Inbox Content
</div>
<div id="outbox" class="tab-pane fade">
Outbox Content
</div>
<div id="compose" class="tab-pane fade">
Compose Content
</div>
</div>
</div>
<script>
$(function () {
var hash = window.location.hash;
hash && $('ul.nav a[href="' + hash + '"]').tab('show');
});
</script>
</body>
</html>
Hope this will save your time.
Here is what i did, really simple, and provided your tab links have an ID associated with them you can get the href attribute and pass that over to the function that shows the tab contents:
<script type="text/javascript">
jQuery(document).ready(function() {
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
var tab = jQuery(hash.replace(prefix,"")).attr('href');
jQuery('.nav-tabs a[href='+tab+']').tab('show');
}
});
</script>
Then in your url you can add the hash as something like: #tab_tab1, the 'tab_' part is removed from the hash itself so the ID of the actual tab link in the nav-tabs (tabid1) is placed after this, so your url would look something like: www.mydomain.com/index.php#tab_tabid1.
This works perfect for me and hope it helps someone else :-)
If it matters to anybody, the following code is small and works flawless, to get a single hash value from the URL and show that:
<script>
window.onload = function () {
let url = document.location.toString();
let splitHash = url.split("#");
if (splitHash[1]) {document.getElementById(splitHash[1]).click();}
};
</script>
what it does is it retrieves the id and fires the click event. Simple.
I just had this issue, but needed to handle multiple tab levels. The code is rather ugly (see comments), but does its job: https://gist.github.com/JensRantil/4721860 Hopefully someone else will find it useful (and feel free to propose better solutions!).
This is my solution to handle nested tabs.
I just added a function to check if the active tab has a parent tab to be activated.
This is the function:
function activateParentTab(tab) {
$('.tab-pane').each(function() {
var cur_tab = $(this);
if ( $(this).find('#' + tab).length > 0 ) {
$('.nav-tabs a[href=#'+ cur_tab.attr('id') +']').tab('show');
return false;
}
});
}
And can be called like this (Based on #flynfish's solution):
var hash = document.location.hash;
var prefix = "";
if (hash) {
$('.nav-tabs a[href='+hash.replace(prefix,"")+']').tab('show');
activateParentTab(hash);
}
// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
This solution works pretty fine to me at the moment.
Hope this can be useful for someone else ;)
I had to modify some bits for this to work for me.
I am using Bootstrap 3 and jQuery 2
// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "!";
if (hash) {
hash = hash.replace(prefix,'');
var hashPieces = hash.split('?');
activeTab = $('[role="tablist"] a[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');
}
// Change hash for page-reload
$('[role="tablist"] a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
Combining peices from other answers, here is a solution that can open many levels of nested tabs:
// opens all tabs down to the specified tab
var hash = location.hash.split('?')[0];
if(hash) {
var $link = $('[href=' + hash + ']');
var parents = $link.parents('.tab-pane').get();
$(parents.reverse()).each(function() {
$('[href=#' + this.id + ']').tab('show') ;
});
$link.tab('show');
}
For Bootstrap 5.1 for redirecting to specific tab
var hash = location.hash.replace(/^#/, '');
if (hash) {
var someVarName = $('.nav-tabs a[href="#' + hash + '"]');
var tab = new bootstrap.Tab(someVarName);
tab.show();
}
Change hash for page-reload
$('.nav-tabs a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash;
window.scrollTo(0, 0);
})
I make sth like this for links with ajax #!# (e.g./test.com#!#test3) but you can modify it whatever you like
$(document).ready(function() {
let hash = document.location.hash;
let prefix = "!#";
//change hash url on page reload
if (hash) {
$('.nav-tabs a[href=\"'+hash.replace(prefix,"")+'\"]').tab('show');
}
// change hash url on switch tab
$('.nav-tabs a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
});
Example with simple page on Github here
I know this thread is very old, but I'll leave here my own implementation:
$(function () {
// some initialization code
addTabBehavior()
})
// Initialize events and change tab on first page load.
function addTabBehavior() {
$('.nav-tabs a').on('show.bs.tab', e => {
window.location.hash = e.target.hash.replace('nav-', '')
})
$(window).on('popstate', e => {
changeTab()
})
changeTab()
}
// Change the current tab and URL hash; if don't have any hash
// in URL, so activate the first tab and update the URL hash.
function changeTab() {
const hash = getUrlHash()
if (hash) {
$(`.nav-tabs a[href="#nav-${hash}"]`).tab('show')
} else {
$('.nav-tabs a').first().tab('show')
}
}
// Get the hash from URL. Ex: www.example.com/#tab1
function getUrlHash() {
return window.location.hash.slice(1)
}
Note that I'm using a nav- class prefix to nav links.
Building on Peter's answer, and incorporating https://stackoverflow.com/a/901144/1604205, here's the code in JS:
<script>
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
$activetabhome = (params.activeTab === null || params.activeTab == 'home') ? 'class="active"' : '';
$activetabprofile = (params.activeTab == 'profile') ? 'class="active"' : '';
</script>
<li $activetabhome>Home</li>
<li $activetabprofile>Profile</li>
I made an active state for my menu on a certain urls. I have urls like this:
/products/other-clothing/sporting/adults-anzac-australia-polo
/products/other-clothing/sporting/adults-nz-tee
/products/bags/backpacks
My code gets the folder from after the / so other-clothing, sporting, etc.
It is working fine, I just assume there is a more efficient way to write the code.
Here is my code:
jQuery(".product-nav li a").each(function() {
// URL url
var cat = location.pathname.split("/")[2];
var subcat = location.pathname.split("/")[3];
var c = "/products/" + cat + "/" + subcat;
// A tag url
var acat = this.href.split("/")[4];
var asubcat = this.href.split("/")[5];
var e = "/products/" + acat + "/" + asubcat;
if(e == c) {
jQuery(this).parent().addClass("active");
jQuery(this).parent().parent().parent().addClass("active");
}
});
If anyone can provide a cleaner way of writing the code that'd be great. I probably dont need "/products/" +.
Notice the output of the following expressions:
$('')[0].href;
/*
* http://stackoverflow.com/questions/7564539/match-url-folders-with-a-tag-href-to-make-a-active-state
*/
$('').eq(0).attr('href');
/*
* /questions/7564539/match-url-folders-with-a-tag-href-to-make-a-active-state
*/
So, if your <a> tags contain URLs that start with / then you can compare the .attr('href') with location.pathname. For testing, try running this in console from this page:
$('a').each(function () {
if ($(this).attr('href') == location.pathname) {
$(this).css({
'font-size': '40px',
'background-color': 'lime'
});
}
});
Here's a brief whack at it:
jQuery(".product-nav li a").each(function() {
// URL url
var c = location.pathname.split('/').slice(2, 4)
// A tag url
, e = this.href.split('/').slice(4, 6)
;
if(e[0] == c[0] && e[1] == c[1]) {
jQuery(this).parentsUntil(
'div:not(.subnav)', // go up the tree until the 1st div that isn't .subnav
'.product-nav li, .subnav' // and only match these parents
).addClass('active');
}
});
.parent().parent().parent()... has a pretty bad code smell to it but can't be improved without a look at your markup. You should probably be using .closest() instead.
Interesting question. Here is my attempt to clean it up:
jQuery(function ($) {
function Category(outer, inner) {
this.outer = outer
this.inner = inner
}
Category.fromURL = function (url) {
var parts = url.replace(/^(https?:\/\/.*?)?\//, "").split("/")
return new Category(parts[1], parts[2])
}
Category.prototype.equals = function (other) {
return this.outer === other.outer
&& this.inner === other.inner
}
var category = Subcategory.fromURL(location.href)
$(".product-nav a").each(function () {
if (Category.fromURL(this.href).equals(category)) {
$(this).closest("li.inner").addClass("active")
$(this).closest("li.outer").addClass("active")
}
})
})