Onglets Twitter Bootstrap: accédez à l'onglet spécifique lors du rechargement de la page ou du lien hypertexte

358

Je développe une page Web dans laquelle j'utilise le framework Bootstrap de Twitter et leurs onglets Bootstrap JS . Cela fonctionne très bien, sauf pour quelques problèmes mineurs, dont l'un est que je ne sais pas comment accéder directement à un onglet spécifique à partir d'un lien externe. Par exemple:

<a href="facility.php#home">Home</a>
<a href="facility.php#notes">Notes</a>

devrait aller à l'onglet Accueil et à l'onglet Notes respectivement lorsque vous cliquez sur les liens d'une page externe

mraliks
la source
49
souhaite que cela a été intégré!
Damon
5
Cette question a également été soulevée ici: github.com/twitter/bootstrap/issues/2415 (et contient quelques solutions).
Ztyx
cela m'a aidé -> stackoverflow.com/questions/12131273/…
JGilmartin
1
Le lien mis à jour vers le problème de bootstrap est github.com/twbs/bootstrap/issues/2415
bmihelac
3
Plugin qui corrige cela: github.com/timabell/jquery.stickytabs
Tim Abell

Réponses:

603

Voici ma solution au problème, un peu en retard peut-être. Mais cela pourrait peut-être aider les autres:

// Javascript to enable link to tab
var url = document.location.toString();
if (url.match('#')) {
    $('.nav-tabs a[href="#' + url.split('#')[1] + '"]').tab('show');
} 

// Change hash for page-reload
$('.nav-tabs a').on('shown.bs.tab', function (e) {
    window.location.hash = e.target.hash;
})
Dubbe
la source
83
J'ajouterais 1 ligne supplémentaire window.scrollTo(0, 0);pour m'assurer que la fenêtre défile toujours vers le haut
Trung Lê
1
$ ('. nav-tabs a [href * = #' + url.split ('#') [1] + ']'). tab ('show'); // Avec un * est plus sûr car sinon il ne correspond qu'au premier # ...
mattangriffel
1
En ligne qui a fonctionné pour moi: window.location.hash && $ ('li a [href = "' + window.location.hash + '"]'). Tab ('show'). Trigger ("click");
Dean Meehan
10
Voici une démo pour Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 et le code source
Zim
2
Après jquery mise à niveau à 1,11 de 1,09 Je reçois cette erreur: Syntax error, unrecognized expression: .nav-tabs a[href=#tab-2]. Résolu en utilisant stackoverflow.com/questions/12131273/…
Pietro Z.
213

MISE À JOUR

Pour Bootstrap 3, passez .on('shown', ...)à.on('shown.bs.tab', ....)


Ceci est basé sur réponse @dubbe et cette réponse SO acceptée . Il gère le problème avec window.scrollTo(0,0)ne fonctionne pas correctement. Le problème est que lorsque vous remplacez le hachage d'URL sur l'onglet affiché, le navigateur défile jusqu'à ce hachage car il s'agit d'un élément sur la page. Pour contourner ce problème, ajoutez un préfixe afin que le hachage ne fasse pas référence à un élément de page réel

// 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);
});

Exemple d'utilisation

Si vous avez un onglet avec id = "mytab", vous devez mettre votre lien comme ceci:

<a href="yoursite.com/#tab_mytab">Go to Specific Tab </a>
poisson-mouche
la source
1
Existerait-il un moyen simple de référencer des signets situés sous un onglet spécifique? J'ai cinq onglets sur ma page, et sous ceux-ci, j'ai un certain nombre de signets. Ce que je voudrais, c'est rendre ces signets pouvant être liés depuis l'extérieur de l'onglet.
nize
@nize si vous créez un jsfiddle avec ce que vous essayez de faire, j'essaierai d'y jeter un œil.
flynfish
1
Voici une démo Bootlpy pour Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 et le code source
Zim
L'exemple ci-dessus ne contient pas les guillemets doubles sur le href. la ligne 5 devrait être:$('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
Ponyboy
Fonctionne pour moi, sauf que j'ai dû supprimer la dernière barre oblique (avant le #) dans 'yoursite.com/anotherpage/#tab_mytab' sinon cela a fait des ravages avec le chargement de la page.
Alexander
52

vous pouvez déclencher un clickévénement sur le lien de l'onglet correspondant:

$(document).ready(function(){

  if(window.location.hash != "") {
      $('a[href="' + window.location.hash + '"]').click()
  }

});
Marian Theisen
la source
Merci pour le conseil! Cela a très bien fonctionné avec un petit problème. L'actualisation de la page ne l'amènerait pas au bon onglet. Frapper Ctrl + F5 le ferait. J'ai modifié le code comme suit: `$ (document) .ready (function () {function getUrlVars () {var vars = {}; var parts = window.location.href.replace (/ [? &] + ([ ^ = &] +) = ([^ &] *) / gi, fonction (m, clé, valeur) {vars [clé] = valeur;}); return vars;} var action = getUrlVars () ["action" ]; if (action! = "") {$ ('a [href = "#' + action + '"]'). click ()};}); `
mraliks
44

Il s'agit d'une implémentation améliorée de la solution de dubbe qui empêche le défilement.

// 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
    }
})
Demircan Celebi
la source
21

Bien que la solution JavaScript fournie puisse fonctionner, j'ai opté pour une méthode légèrement différente qui ne nécessite aucun JavaScript supplémentaire, mais nécessite une logique à votre avis. Vous créez un lien avec un paramètre d'URL standard, comme:

<a href = "http://link.to.yourpage?activeTab=home">My Link</a>

Ensuite, vous détectez simplement la valeur de activeTab pour écrire 'class = "active"' dans le <li>

Pseudocode (implémentez en conséquence dans votre langue). Remarque J'ai défini l'onglet 'home' comme actif par défaut si aucun paramètre fourni dans cet exemple.

$activetabhome = (params.activeTab is null or params.activeTab == 'home') ? 'class="active"' : '';
$activetabprofile = (params.activeTab == 'profile') ? 'class="active"' : '';

<li $activetabhome><a href="#home">Home</a></li>
<li $activetabprofile><a href="#profile">Profile</a></li>
Peter
la source
Je préfère votre solution à la solution JS pour une raison simple est que JS location.hash sauterait à l'ID qui provoque la position du curseur de haut en bas.
Trung Lê
Je préfère cette solution. En fait, j'ai créé de nouvelles routes pour les onglets et la vue régénérée en définissant la classe active en conséquence. Cela évite les maux de tête liés au redimensionnement de la page, au hachage d'URL et au défilement de la page tous ensemble.
Vijay Meena
10

Je ne suis pas un grand fan de if ... else; j'ai donc adopté une approche plus simple.

$(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;
    })
});
  1. Choisissez un onglet par défaut (généralement le premier)
  2. Passez à tab (si un tel élément est bien présent; laissez jQuery le gérer); Rien ne se passe si un hachage incorrect est spécifié
  3. [Facultatif] Mettez à jour le hachage si un autre onglet est choisi manuellement

N'adresse pas le défilement au hachage demandé; mais le devrait- il?

visitesb
la source
8

Cela fonctionne dans Bootstrap 3 et améliore les 2 meilleures réponses de dubbe et flynfish en intégrant également la réponse de GarciaWebDev (qui permet les paramètres d'URL après le hachage et provient directement des auteurs de Bootstrap sur le suivi des problèmes de github):

// 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);
});
greggdavis
la source
1
cela ne fonctionne pas dans Bootstrap 3, 'shown'devrait être 'shown.bs.tab'selon les documents: getbootstrap.com/javascript/#tabs-events . Je suis perplexe quant à pourquoi, mais quand j'ai essayé de modifier votre message, il a été rejeté ...
YPCrumble
6

Ce code sélectionne l'onglet de droite en fonction du #hash et ajoute le #hash de droite lorsqu'un onglet est cliqué. (cela utilise jquery)

Dans 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)

ou en 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);
    });
});
Sucrenoir
la source
assurez-vous de le mettre après le chargement de jquery. Je le mettais au milieu d'une page (c'était un endroit facile à insérer pour les tests) et cela n'a pas fonctionné. Le mettre après avoir chargé jquery fonctionne très bien.
Ron
6

S'appuyer sur la solution de Demircan Celebi; Je voulais que l'onglet s'ouvre lors de la modification de l'url et ouvre l'onglet sans avoir à recharger la page depuis le serveur.

<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>
Gavin
la source
5

@flynfish + @Ztyx solution que j'utilise pour les onglets imbriqués:

    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);
            }
        });
    }

les enfants doivent avoir class = "nested"

Artem Kashin
la source
5

J'ai trouvé une solution qui utilise le hachage d'URL ou localStorage en fonction de la disponibilité de ce dernier avec le code ci-dessous:

$(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');
    }
});
Vaibhav
la source
4

Je vous suggère d'utiliser le code fourni par les auteurs de Bootstrap sur leur outil de suivi des problèmes sur GitHub :

var hash = location.hash
  , hashPieces = hash.split('?')
  , activeTab = $('[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');

Vous pouvez trouver sur le lien vers le problème plus d'informations sur les raisons pour lesquelles ils n'ont pas choisi de soutenir cela.

Alejandro García Iglesias
la source
4

J'ai essayé plusieurs façons discutées ci-dessus et vous vous retrouvez avec la solution de travail suivante, copiez et collez simplement dans votre éditeur pour essayer. Pour tester, changez simplement le hachage en boîte de réception, boîte d'envoi, composez dans l'URL et appuyez sur la touche Entrée.

<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>

J'espère que cela vous fera gagner du temps.

Abhimanyu
la source
3

Voici ce que j'ai fait, vraiment simple, et à condition que vos liens d'onglet aient un ID associé, vous pouvez obtenir l'attribut href et le transmettre à la fonction qui affiche le contenu de l'onglet:

<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>

Ensuite, dans votre URL, vous pouvez ajouter le hachage comme quelque chose comme: # tab_tab1, la partie 'tab_' est supprimée du hachage lui-même afin que l'ID du lien d'onglet réel dans les nav-tabs (tabid1) soit placé après cela, donc votre url ressemblerait à quelque chose comme: www.mydomain.com/index.php#tab_tabid1.

Cela fonctionne parfaitement pour moi et j'espère que cela aide quelqu'un d'autre :-)

Derek Buntin
la source
2

Ceci est ma solution pour gérer les onglets imbriqués. Je viens d'ajouter une fonction pour vérifier si l'onglet actif a un onglet parent à activer. Voici la fonction:

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;
        }
    });
}

Et peut être appelé comme ceci (basé sur la solution de @ flynfish):

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);
});

Cette solution me convient très bien pour le moment. J'espère que cela peut être utile pour quelqu'un d'autre;)

Stefano Marra
la source
2

J'ai dû modifier quelques bits pour que cela fonctionne pour moi. J'utilise Bootstrap 3 et 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);
});
ruifn
la source
Excellente réponse, sauf que j'ai dû remplacer le "!" préfixe avec "tab_". Sinon, a parfaitement fonctionné.
koziez
2

Insérez simplement ce code sur votre 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);
  });
});

Amin Gholibeigian
la source
1

Je viens d'avoir ce problème, mais je devais gérer plusieurs niveaux d'onglets. Le code est plutôt moche (voir commentaires), mais fait son travail: https://gist.github.com/JensRantil/4721860 J'espère que quelqu'un d'autre le trouvera utile (et n'hésitez pas à proposer de meilleures solutions!).

Ztyx
la source
1

En combinant des morceaux d'autres réponses, voici une solution qui peut ouvrir de nombreux niveaux d'onglets imbriqués:

// 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');
}
cweston
la source
ne fonctionne qu'à 2 niveaux d'imbrication, le 3ème niveau pose problème.
Nicholas Hamilton
Je viens de tester cela sur trois niveaux d'onglets, et cela semble fonctionner pour moi. Êtes-vous sûr que ce n'est pas un problème avec votre implémentation? Quel problème rencontrez-vous?
cweston
Tout onglet au 1er niveau et au 2e niveau fonctionne bien, cependant, au 3e niveau, lors de l'actualisation de la page (ou de la soumission du formulaire), lorsque la page se rouvre, le focus est donné au premier onglet du 2e niveau.
Nicholas Hamilton
Donc ça a bien fonctionné (il y avait une faute de frappe mineure dans mon code), cependant après la correction de faute de frappe, uniquement avec $('.nav-tabs li a').click( function(e) { history.pushState( null, null, $(this).attr('href') );});dans le javascript au-dessus de votre code.
Nicholas Hamilton
1

Si cela importe pour tout le monde, le code suivant est petit et fonctionne parfaitement, pour obtenir une seule valeur de hachage à partir de l'URL et montrer que:

<script>
    window.onload = function () {
        let url = document.location.toString();
        let splitHash = url.split("#");
        document.getElementById(splitHash[1]).click();
    };
</script>

ce qu'il fait, c'est qu'il récupère l'id et déclenche l'événement click. Facile.

Sam
la source
0

Je fais quelque chose comme ça pour les liens avec ajax #!#(par exemple / test.com #! # Test3) mais vous pouvez le modifier comme bon vous semble

$(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);
       });
 });

Exemple avec une page simple sur Github ici

eudaimonia
la source
0

Je sais que ce fil est très ancien, mais je vais laisser ici ma propre implémentation:

$(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)
}

Notez que j'utilise un nav-préfixe de classe pour naviguer dans les liens.

Renan Coelho
la source