Twitter Bootstrap-onglets-URL ne change pas

J'utilise Twitter Bootstrap et ses "onglets".

J'ai le code suivant:

<ul class="nav nav-tabs">
    <li class="active"><a data-toggle="tab" href="#add">add</a></li>
    <li><a data-toggle="tab" href="#edit" >edit</a></li>
    <li><a data-toggle="tab" href="#delete" >delete</a></li>
</ul>

Les onglets fonctionnent correctement, mais la dans l'URL n'est pas ajouté le #ajouter #modifier, #supprimer.

Lorsque je supprime data-toggle l'URL change, mais les onglets ne fonctionnent pas.

Des solutions pour cela?

91
demandé sur Nope 2012-08-26 19:19:06

14 réponses

Essayez ce code. Il ajoute l'onglet href à l'url + ouvre l'onglet en fonction du hachage lors du chargement de la 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() || $('html').scrollTop();
    window.location.hash = this.hash;
    $('html,body').scrollTop(scrollmem);
  });
});
227
répondu tomaszbak 2016-03-23 13:56:57

Il y a trois composants nécessaires pour une solution complète:

  1. affiche l'onglet correct lorsque la page est chargée s'il y a un hachage dans L'URL.
  2. Modification du hachage dans L'URL lorsque l'onglet est modifié.
  3. changez l'onglet lorsque le hachage change dans L'URL (boutons Précédent / Suivant), et assurez-vous que le premier onglet est correctement cyclé.

Je ne pense pas que les commentaires ici, ni la réponse acceptée, gèrent tous ces scénarios.

Comme il y a tout à fait un peu impliqué, je pense que c'est le plus propre comme un petit plugin jQuery: https://github.com/aidanlister/jquery-stickytabs

, Vous pouvez appeler le plugin comme ceci:

$('.nav-tabs').stickyTabs();

J'ai fait un billet de blog pour cela, http://aidanlister.com/2014/03/persisting-the-tab-state-in-bootstrap/

46
répondu Aidan 2015-04-04 11:54:34

En utilisant data-toggle="tab" demande à le plugin de gérer les onglets, qui tout en le faisant appelle preventDefault sur l'événement (code sur github ).

Vous pouvez utiliser votre propre activation d'onglet, et laisser passer l'événement:

$('.nav-tabs a').click(function (e) {
    // No e.preventDefault() here
    $(this).tab('show');
});

Et vous devez supprimer l'attribut data-toggle="tab"

Vérifier , le doc si vous avez des doutes.

22
répondu Sherbrow 2012-08-26 15:59:25

Comme vos éléments d'ancrage modifient déjà le hachage de l'url, l'écoute de l'événement onhashchange est une autre bonne option. Comme @flori l'a déjà mentionné, cette méthode fonctionne bien avec le bouton de retour du navigateur.

var tabs$ = $(".nav-tabs a");

$( window ).on("hashchange", function() {
    var hash = window.location.hash, // get current hash
        menu_item$ = tabs$.filter('[href="' + hash + '"]'); // get the menu element

    menu_item$.tab("show"); // call bootstrap to show the tab
}).trigger("hashchange");

Enfin, le déclenchement de l'événement juste après avoir défini l'écouteur aidera également à afficher l'onglet de droite lors du chargement de la page.

9
répondu halilb 2016-11-02 10:30:58

Ma solution à votre problème:

Ajoutez D'abord un nouvel attribut data-value à chaque lien a, comme ceci:

<ul class="nav nav-tabs">
    <li class="active">
        <a data-toggle="tab" href="#tab-add" data-value="#add">add</a>
    </li>
    <li>
        <a data-toggle="tab" href="#tab-edit" data-value="#edit">edit</a>
    </li>
    <li>
        <a data-toggle="tab" href="#tab-delete" data-value="#delete">delete</a>
    </li>
</ul>

Deuxièmement, changez les ID des onglets, par exemple de add à tab-add, Mettez également à jour les hrefs pour inclure le préfixe tab-:

<div class="tab-content">
    <div class="tab-pane" id="tab-add">Add panel</div>
    <div class="tab-pane" id="tab-edit">Edit panel</div>
    <div class="tab-pane" id="tab-delete">Panel panel</div>
</div>

Et enfin le code js:

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

Voici jsFiddle - mais cela ne fonctionne pas à cause de l'iframe utilisé par jsFiddle, mais vous pouvez lire la source de ma solution.

3
répondu psulek 2013-08-29 09:40:37

Il existe également un moyen simple de réagir aux changements de hachage (par exemple, le bouton Retour). Ajoutez simplement un écouteur d'événement hashchange à la solution tomaszbak:

$(function(){
  // Change tab on load
  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);
  });

  // Change tab on hashchange
  window.addEventListener('hashchange', function() {
    var changedHash = window.location.hash;
    changedHash && $('ul.nav a[href="' + changedHash + '"]').tab('show');
  }, false);
});
2
répondu Flori 2013-09-24 09:44:37

Même problème avec CakePHP avec Bootstrap 3 onglets, plus quand j'envoie avec URL externe et ancre, il saute à la section perdre mon menu, après examen de nombreuses solutions ont fait cela...

Grâce à: http://ck.kennt-wayne.de/2012/dec/twitter-bootstrap-how-to-fix-tabs

$(document).ready(function()
 {  
//Redirecciona al tab, usando un prefijo al cargar por primera vez, al usar redirect en cake #_Pagos    
//Redirecciona al tab, usando #Pagos
/* Automagically jump on good tab based on anchor; for page reloads or links */
 if(location.hash) 
  {
     $('a[href=' + location.hash + ']').tab('show');         
  }


//Para evitar el bajar al nivel del tab, (al mostrarse el tab subimos)
$('a[data-toggle="tab"]').on('shown.bs.tab', function(e) 
{
    location.hash = $(e.target).attr('href').substr(1);
    scrollTo(0,0);      
});



//Actualiza el URL con el anchor o ancla del tab al darle clic
 /* Update hash based on tab, basically restores browser default behavior to
 fix bootstrap tabs */
$(document.body).on("click", "a[data-toggle]", function(event) 
  {
    location.hash = this.getAttribute("href");
  });


//Redirecciona al tab, al usar los botones de regresar y avanzar del navegador.
/* on history back activate the tab of the location hash if exists or the default tab if no hash exists */   
$(window).on('popstate', function() 
{
  //Si se accesa al menu, se regresa al tab del perfil (activo default), fixed conflict with menu
  //var anchor = location.hash || $("a[data-toggle=tab]").first().attr("href");
  var anchor = location.hash;
  $('a[href=' + anchor + ']').tab('show');

});   

});//Fin OnReady
2
répondu Henry Gabriel González Montejo 2014-10-07 17:41:41

Le plus simple, en supposant que vous utilisez la syntaxe documentée data-toggle="tab" décrite ici:

$(document).on('shown.bs.tab', function(event) {
  window.location.hash = $(event.target).attr('href');
});
0
répondu Fred 2013-11-24 23:50:25

Pour ceux qui utilisent Ruby on Rails ou tout autre script côté serveur, vous voudrez utiliser l'option anchor sur les chemins. C'est parce qu'une fois que la page se charge, elle n'a pas le hachage D'URL disponible. Vous voudrez fournir l'onglet correct via votre lien ou la soumission de formulaire.

<%= form_for @foo, url: foo_path(@foo, anchor: dom_id(foo)) do |f| %>
# Or
<%= link_to 'Foo', foo_path(@foo, anchor: dom_id(foo)) %>

Si vous utilisez un préfixe pour empêcher la fenêtre de sauter à l'id:

<%= form_for @foo, url: foo_path(@foo, anchor: "bar_#{dom_id(foo)}") do |f| %>

Alors vous CoffeeScript:

  hash = document.location.hash
  prefix = 'bar_'
  $('.nav-tabs a[href=' + hash.replace(prefix, '') + ']').tab 'show' if hash
  $('.nav-tabs a').on 'shown.bs.tab', (e) ->
    window.location.hash = e.target.hash.replace '#', '#' + prefix

Ou JavaScript:

var hash, prefix;

hash = document.location.hash;
prefix = 'bar_';

if (hash) {
  $('.nav-tabs a[href=' + hash.replace(prefix, '') + ']').tab('show');
}

$('.nav-tabs a').on('shown.bs.tab', function(e) {
  window.location.hash = e.target.hash.replace('#', '#' + prefix);
});

Cela devrait fonctionner dans Bootstrap 3.

0
répondu Mohamad 2014-06-05 18:07:47

Merci à @ tomaszbak pour la solution originale cependant puisque mes modifications ont été rejetées et que je ne peux pas commenter son message, je vais laisser ma version légèrement améliorée et plus lisible ici.

Il fait fondamentalement la même chose mais si résout le problème de compatibilité entre les navigateurs que j'ai eu avec le sien.

$(document).ready(function(){
   // go to hash on window load
   var hash = window.location.hash;
   if (hash) {
       $('ul.nav a[href="' + hash + '"]').tab('show');
   }
   // change hash on click
   $('.nav-tabs a').click(function (e) {
       $(this).tab('show');
       if($('html').scrollTop()){
           var scrollmem = $('html').scrollTop(); // get scrollbar position (firefox)
       }else{
           var scrollmem = $('body').scrollTop(); // get scrollbar position (chrome)
       }
       window.location.hash = this.hash;
       $('html,body').scrollTop(scrollmem); // set scrollbar position
   });
});
0
répondu Fuxy 2016-03-23 13:33:01

Voici une option utilisant history.pushState afin que vous puissiez utiliser l'historique de votre navigateur pour revenir à un onglet précédent

  $(document).ready(function() {
  // add a hash to the URL when the user clicks on a tab
  $('a[data-toggle="tab"]').on('click', function(e) {
    history.pushState(null, null, $(this).attr('href'));
  });
  // navigate to a tab when the history changes
  window.addEventListener("popstate", function(e) {
    var activeTab = $('[href=' + location.hash + ']');
    if (activeTab.length) {
      activeTab.tab('show');
    } else {
      $('.nav-tabs a:first').tab('show');
    }
  });
});
0
répondu Adam Hey 2016-04-11 09:03:05

J'utilise Bootstrap 3.3.* et aucune de la solution ci-dessus ne m'a aidé, même marqué comme réponse. Je viens d'Ajouter ci-dessous script et travaillé.

$(function(){
    var hash = document.location.hash;
    if (hash) {
       $('.navbar-nav a[href="' + hash + '"]').tab('show');
    }
    $('a[data-toggle="tab"]').on('click', function (e) {
       history.pushState(null, null, $(this).attr('href'));
    });
});

J'espère que cela vous aidera.

0
répondu Abhimanyu 2016-07-21 07:48:32

Aucun de ce qui précède n'a fonctionné pour moi, alors voici comment j'ai fait fonctionner le mien:

  1. ajouter class="tab-link" à tous les liens ayant besoin de cette fonctionnalité
  2. Ajoutez le code suivant à votre javascript:
    window.addEventListener
    (
        'popstate',
        function( event )
        {
            tab_change();
        }
    );

    function tab_change()
    {
        var hash = window.location.hash;
        hash && $( 'ul.nav a[href="' + hash + '"]' ).tab( 'show' );

        $( '.tab-link' ).click
        (
            function( e )
            {
                $( this ).tab( 'show' );

                var scrollmem = $( 'body' ).scrollTop() || $( 'html' ).scrollTop();
                window.location.hash = this.hash;
                $( 'html,body' ).scrollTop( scrollmem );

                $( 'ul.nav-tabs a[href="' + window.location.hash + '"]' ).tab( 'show' );
            }
        );
    }

0
répondu simonl 2017-03-10 10:44:08

Cela corrige également un onglet extrêmement obscur un href ne tirant pas lors de l'utilisation de jquery et bootstrap

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 

<script type="text/javascript">
$('.nav-tabs a').click(function (e) {
    // No e.preventDefault() here.
    $(this).tab('show');
});
</script>

<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js"></script>
-2
répondu Ray 2012-12-04 20:12:20