web-dev-qa-db-fra.com

La bascule de classe active de Twitter Bootstrap Tabs ne fonctionne pas

J'utilise les tablatures de navigation et les pilules de navigation de Twitter bootstrap. Ceci est mon code html:

<div class="Header2" style="background-color:#1E3848">
    <div id="headerTab">
        <ul class="nav nav-tabs">
            <li class="active ans-tab"> <a href="http://myweb.com/">Home</a></li>
            <li class="topTab"><a href="http://myweb.com/score/">Score</a></li>
            <li class="topTab"><a href="http://myweb.com/leaderboards/">Leaderboards</a></li>
        </ul>
    </div>
    <div id="subHeaderTabPlayer">
        <ul class="nav nav-pills">
            <li class="active"> <a href="http://myweb.com/">Top</a></li>
            <li><a href="http://myweb.com/rules/" data-toggle="pill">Rules</a></li>
            <li><a href="http://myweb.com/player/" data-toggle="pill">Player</a></li>
            <li><a href="http://myweb.com/categories/" data-toggle="pill">Categories</a></li>
        </ul>
    </div>
</div>

Maintenant, si j'ajoute les attributs data-toggle="pill" et data-toggle="tab", l'onglet avec la classe active est remplacé par celui sur lequel j'ai cliqué. Cependant, href ne fonctionne plus. Si je n'utilise pas ces classes, href fonctionne mais la classe active ne change pas et reste toujours à l'élément que cette classe a été donnée au chargement de la page. 

J'ai même essayé d'utiliser jQuery pour basculer le comportement des classes et cela ne fonctionne pas aussi bien. Mon code de script est:

<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript">
    $(window).load(function(){
        document.getElementById( 'subHeaderTabPlayer' ).style.display = 'none';
        $('ul.nav-tabs li a').click(function (e) {
            var activeTab= document.getElementByClass('active');
            activeTab.removeAttribute("class");

            $('ul.nav-tabs li.active').removeClass('active')
            $(this).parent('li').addClass('active')
        })
        $('ul.nav-pills li a').click(function (e) {
            $('ul.nav-pills li.active').removeClass('active');
            $(this).parent('li').addClass('active');
        })
        $(".ans-tab").click(function() {
            document.getElementById('subHeaderTabPlayer').style.visibility = 'visible';
            document.getElementById('subHeaderTabPlayer' ).style.display = 'block';
        });
        $(".topTab").click(function() {
            document.getElementById('subHeaderTabPlayer').style.visibility = 'collapse';
            document.getElementById('subHeaderTabPlayer' ).style.display = 'none';
        });
    });
</script>
21
CodeMonkey

Les onglets et les pilules de navigation Bootstrap fonctionnent avec un plugin JS. Le plugin est chargé sur la page et prend en charge la mise en surbrillance et la mémorisation de l'onglet ou de la pilule actuellement actif. Il désactive les attributs href s'ils renvoient vers d'autres pages, simplement parce que lorsque vous cliquez sur un lien vers une autre page, une nouvelle page est chargée. Le JS est ensuite rechargé pour cette nouvelle page et il ne sait pas quel onglet ou pilule est actuellement actif. Ils sont conçus pour fonctionner avec des applications d'une seule page ou des liens vers des ancres sur la même page, et ils fonctionnent parfaitement à cette fin.

L'approche jQuery échoue pour la même raison, mais pourrait être plus facile à expliquer.

$('ul.nav-pills li a').click(function (e) {
  $('ul.nav-pills li.active').removeClass('active')
  $(this).parent('li').addClass('active')
})

Vous cliquez sur un lien, JS s’éteint et change de classe, mais seulement s’il a suffisamment de temps pour le faire avant que la page suivante ne soit chargée, cette page suivante est chargée car l’attribut href sur le lien indique au navigateur de naviguer vers une nouvelle page. page. Et la nouvelle page charge à nouveau votre JS, il ne peut pas mémoriser les variables de la page précédente, telles que l'onglet ou la pilule censé être actif.

Si vous souhaitez naviguer vers d'autres pages, vous pouvez également définir la classe active dans le bon onglet pour la page en cours de chargement.

Si vous avez vraiment besoin de le faire côté client, vous pouvez le faire et le charger sur chaque page.

$(document).ready(function () {

  // Set BaseURL
  var baseURL = 'http://myweb.com/'

  // Get current URL and replace baseURL
  var href = window.location.href.replace(baseURL, '');

  // Remove trailing slash
  href = href.substr(-1) == '/' ? href.substr(0, href.length - 1) : href;

  // Get last part of current URL
  var page = href.substr(href.lastIndexOf('/') + 1);

  // Add trailing slash if not empty (empty means we're currently at baseURL)
  page = page != '' ? page + '/' : page;

  // Select link based on href attribute and set it's closest 'li' to 'active'. 
  // .siblings('.active').removeClass() is only needed if you have a default 'active li'.
  $('a[href="' + baseURL + page + '"]', '.nav li').closest('li').addClass('active').siblings('.active').removeClass();

});

Il définit l'onglet actif en fonction de la dernière partie de l'URL, il est cependant spécifique à votre scénario (et précédemment à mon scénario). Vous devrez l'adapter si des extensions de fichier ou des paramètres de requête sont impliqués. Chaque page doit au moins avoir un lien vers elle-même. Et il a de préférence le même en-tête avec les mêmes onglets et les mêmes pilules que toutes les autres pages.

Ces deux derniers points me font encore penser "si vous devez avoir autant de contrôle sur ce qui est rendu sur la page, vous avez probablement accès au côté serveur", et si tel est le cas, vous pourriez vous y trouverez également une solution, car chaque lien effectue de toute façon une nouvelle demande au serveur. Et votre solution n'aurait pas à compter sur un JavaScript moins robuste pour fonctionner.

C’est donc ce que j’avais fait à un moment donné, vous pouvez l’améliorer ou mettre en œuvre une solution permettant de publier des données sur la page suivante et de les lire en JavaScript (ce qui serait probablement plus simple et plus robuste si vous aviez des extensions de fichiers ou les chaînes de requête à traiter).

Bonne chance! :)

28
Mathijs Flietstra

Quelque chose à considérer: Si chaque élément li utilise un contrôleur différent, voici quelque chose que vous pouvez essayer.

Comment obtenir la navigation Twitter-Bootstrap pour afficher le lien actif?

Votre code pourrait ressembler à quelque chose comme ça:

<ul class="nav nav-pills">
  <li class="<%= 'active' if params[:controller] == 'home' %>"> <a href="link" data-toggle="pill">Top</a></li>
  <li class="<%= 'active' if params[:controller] == 'rules' %>"><a href="link" data-toggle="pill">Rules</a></li>
  <li class="<%= 'active' if params[:controller] == 'player' %>"><a href="link" data-toggle="pill">Player</a></li>
  <li class="<%= 'active' if params[:controller] == 'categories' %>"><a href="link" data-toggle="pill">Categories</a></li>
</ul>
3
syeh

Cet exemple a fonctionné pour moi:

$leftBlock.on("click", "#navFinished", function(){
  $('ul.nav-pills li.active').removeClass('active');
  $(this).addClass('active');
});

Bien que cet exemple n'ait pas fonctionné

$leftBlock.on("click", "#navFinished", function(){
  $('ul.nav-pills li.active').removeClass('active')
  $(this).parent('li').addClass('active')
})

Enlever .parent ("li") a aidé.

1
user3941146

J'ai suivi la solution @syeh et je l'ai bien compris. Ci-dessous, un extrait de mon code.

<ul class="nav nav-pills">
   <li <?php if (strchr($this->pageTitle,' Job') === ' Job') echo 'class=active';?>><?php echo CHtml::link('JOBS', array('Job/index'));?></li>
   <li <?php if (strchr($this->pageTitle,'Artisan') === 'Artisan') echo 'class=active';?>><?php echo CHtml::link('ARTISANS', array('Artisan/index'));?></li>
   <li <?php if (strchr($this->pageTitle,'Task') === 'Task') echo 'class=active';?>><?php echo CHtml::link('TASKS',array('Task/index'));?></li>
</ul>
0
user3702201

J'avais un problème similaire: lorsque vous cliquez dessus, les onglets deviennent actifs mais ne suppriment pas correctement la classe active des autres onglets (c'est-à-dire que chaque onglet sur lequel l'utilisateur a cliqué sur une vue de page aura la classe active.

Passer d'un <ol> à un <ul> a permis aux onglets de se comporter correctement.

0
praniclift

Ceci est une solution plus généralisée côté client utilisant jQuery. Cela suppose seulement que vos onglets ont l'attribut data-toggle et que chaque groupe d'onglets est encapsulé dans un type d'élément conteneur.

$('[data-toggle="tab"],[data-toggle="pill"]').click(function() { 
    $(this).parent().children('.active[data-toggle="tab"],.active[data-toggle="pill"]').removeClass('active'); 
    $(this).addClass('active'); 
});
0
kwcto