Twitter Bootstrap - Tabs - URL ändert sich nicht

109

Ich benutze Twitter Bootstrap und seine "Tabs".

Ich habe folgenden Code:

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

Die Registerkarten funktionieren ordnungsgemäß, aber in der URL wird nicht #add, #edit, #delete hinzugefügt.

Wenn ich data-toggledie URL-Änderungen entferne , funktionieren die Registerkarten jedoch nicht.

Irgendwelche Lösungen dafür?

Ivanka Todorova
quelle
1
Plugin, das dies behebt: github.com/timabell/jquery.stickytabs
Tim Abell
Dies ist eine ähnliche Frage wie stackoverflow.com/q/18999501/873282
koppor

Antworten:

269

Versuchen Sie diesen Code. Es fügt Tab href zu URL hinzu + öffnet Tab basierend auf Hash beim Laden der Seite:

$(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);
  });
});
tomaszbak
quelle
1
Es funktioniert sehr gut. +1. Aber was ist der Grund für "Hash && $ .." aus dem Selektor ist die Registerkarte "Show", aber was bedeutet "Hash &&". Danke
richardhell
4
&&bedeutet ANDalso, wenn die linke davon wahr ist ( hashnicht 0, null oder leer) und die rechte gleich wahr ist, dann tun Sie etwas, aber die Zeile endet mit a, ;so dass vorher nichts zu tun ist ;und es keine Rolle spielt, ob a Die Registerkarte wird angezeigt oder nicht und es spielt keine Rolle, was .tab('show')zurückgegeben wird. Es wird weiterhin versucht. Wenn bei der Auswertung der Logik auf diese Weise der erste Teil der Gleichung (vorher &&) falsch ist, muss die Auswertung nicht fortgesetzt werden, sodass die Registerkarte nicht angezeigt wird. Sie könnten den gleichen Effekt wie if(hash){ $('ul.nav a[href="' + hash + '"]').tab('show'); }
folgt
1
TL; DR: a && b;bedeutet versuchen aund dann nur, wenn es wahr ist, versuchen b. Zeichenfolgen sind wahr, wenn sie nicht leer sind.
Vahanpwns
8
Wie würde ich es so machen, dass die Seite oben nur neu geladen wird, wenn ich die URL "#" verwende? Im Moment wird nach unten gescrollt, wo die Registerkarten beginnen. Ich möchte nur nach oben zur eigentlichen Seite
scrollen
1
funktioniert gut, musste aber "$ ('. nav-tabs a') ersetzen. click (" durch "$ ('# navtabs a'). on ('selected.bs.tabs", auf Bootstrap 3
Zzirconium
49

Für eine Komplettlösung sind drei Komponenten erforderlich:

  1. Zeigen Sie beim Laden der Seite die richtige Registerkarte an, wenn die URL einen Hash enthält.
  2. Ändern des Hashs in der URL, wenn die Registerkarte geändert wird.
  3. Ändern Sie die Registerkarte, wenn sich der Hash in der URL ändert (Schaltflächen Zurück / Vorwärts), und stellen Sie sicher, dass die erste Registerkarte korrekt durchlaufen wird.

Ich denke, keiner der Kommentare hier oder die akzeptierte Antwort behandeln all diese Szenarien.

Da es einiges zu tun gibt, denke ich, dass es als kleines jQuery-Plugin am besten ist: https://github.com/aidanlister/jquery-stickytabs

Sie können das Plugin folgendermaßen aufrufen:

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

Ich habe dafür einen Blog-Beitrag verfasst: http://aidanlister.com/2014/03/persisting-the-tab-state-in-bootstrap/

Aidan
quelle
Ich gab es sein eigenes Git-Repo: github.com/timabell/jquery.stickytabs - vielen Dank für das Plugin, funktioniert ein Vergnügen.
Tim Abell
+1 für diese Lösung, da sie auch beim Back / Next-Browsing funktioniert, was bei der @ tomaszback-Lösung nicht der Fall ist. Vielen Dank!
Bitfidget
Das ist großartig und funktioniert gut, aber nicht, wenn ich die Seite mit einem Hash in der URL lade. Ich werde weiter herumgraben, um sicherzugehen, dass ich etwas falsch gemacht habe (höchstwahrscheinlich). Ich werde es jedoch mit +1
MattBoothDev
27

Using data-toggle="tab" fordert das Plugin auf, die Registerkarten zu behandeln, die dabei preventDefaultdas Ereignis aufrufen ( Code auf Github ).

Sie können Ihre eigene Tab-Aktivierung verwenden und das Ereignis durchlaufen lassen:

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

Und Sie müssen das Attribut entfernen data-toggle="tab"

Prüfen das Dokument, wenn Sie Zweifel haben.

Sherbrow
quelle
11

Da Ihre Ankerelemente den URL-Hash bereits ändern, ist das Abhören des Onhashchange- Ereignisses eine weitere gute Option. Wie bereits erwähnt, funktioniert diese Methode gut mit der Zurück-Schaltfläche des Browsers.

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

Wenn Sie das Ereignis direkt nach dem Definieren des Listeners auslösen, wird beim Laden der Seite auch die rechte Registerkarte angezeigt.

halilb
quelle
3

Meine Lösung für Ihr Problem:

Fügen Sie data-valuezunächst jedem aLink ein neues Attribut hinzu :

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

Zweitens ändern Sie die IDs von Registerkarten, z. B. von addbis tab-add, und aktualisieren Sie die hrefs mit dem tab-Präfix:

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

Und schließlich js Code:

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

Hier ist jsFiddle - aber es funktioniert nicht wegen des von jsFiddle verwendeten Iframes, aber Sie können die Quelle meiner Lösung lesen.

psulek
quelle
3

Das gleiche Problem mit CakePHP mit Bootstrap 3-Registerkarten. Wenn ich mit einer externen URL und einem Anker sende, springt es zu dem Abschnitt, der mein Menü verliert, nachdem viele Lösungen dies überprüft haben ...

danke an: 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
Henry Gabriel González Montejo
quelle
2

Es gibt auch eine einfache Möglichkeit, auf Hash-Änderungen zu reagieren (z. B. Zurück-Schaltfläche). Fügen Sie der tomaszbak-Lösung einfach einen Listener für Hashchange-Ereignisse hinzu:

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

Ich verwende Bootstrap 3.3. * Und keine der oben genannten Lösungen hat mir geholfen, auch nicht als Antwort 1 markiert. Ich habe gerade unten Skript hinzugefügt und gearbeitet.

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

Hoffe das hilft dir.

Abhimanyu
quelle
0

Am einfachsten, vorausgesetzt, Sie verwenden die hierdata-toggle="tab" beschriebene dokumentierte Syntax :

$(document).on('shown.bs.tab', function(event) {
  window.location.hash = $(event.target).attr('href');
});
Fred
quelle
Dies ändert die URL, kann aber nicht dorthin gehen, wenn Sie auf einen Link klicken, um einen bestimmten Tab zu öffnen
Khrys
0

Wenn Sie Ruby on Rails oder ein anderes serverseitiges Skript verwenden, sollten Sie die anchorOption für Pfade verwenden. Dies liegt daran, dass nach dem Laden der Seite der URL-Hash nicht mehr verfügbar ist. Sie möchten den richtigen Tab über Ihren Link oder Ihre Formularübermittlung angeben.

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

Wenn Sie ein Präfix verwenden, um zu verhindern, dass das Fenster zur ID springt:

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

Dann hast du 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

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

Dies sollte in Bootstrap 3 funktionieren.

Mohamad
quelle
0

Danke an @tomaszbak für die ursprüngliche Lösung. Da meine Änderungen jedoch abgelehnt wurden und ich seinen Beitrag noch nicht kommentieren kann, werde ich meine leicht verbesserte und besser lesbare Version hier .

Es macht im Grunde das gleiche, aber wenn das Cross-Browser-Kompatibilitätsproblem behoben ist, das ich mit seinem hatte.

$(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
   });
});
Fuxy
quelle
Abgelehnt hat bei mir nicht funktioniert (vielleicht war es nur die Firefox-Version). Wie auch immer, ich habe var scrollmem = $ ('body') geändert. ScrollTop () || $ ('html'). scrollTop (); Vielen Dank!
Thomaszbak
1
Ja. Erzählen Sie mir davon, als Sie sagten, dass mir klar wurde, dass es sich um eine Browsersache handelt, und gingen schnell auf Chrom um, um sicherzugehen. Ich wünschte, es gäbe eine Möglichkeit, Kommentare zum Bearbeiten von Bewertungen abzugeben.
Fuxy
0

Hier ist eine Option, mit history.pushStateder Sie Ihren Browserverlauf verwenden können, um zu einer vorherigen Registerkarte zurückzukehren

  $(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');
    }
  });
});
Adam Hey
quelle
0

Keiner der oben genannten Punkte hat für mich funktioniert. Hier ist also, wie ich meinen zum Laufen gebracht habe:

  1. Fügen Sie class="tab-link"allen Links hinzu, die diese Funktionalität benötigen
  2. Fügen Sie Ihrem Javascript den folgenden Code hinzu:
    window.addEventListener
    (
        'popstate',
        Funktion (Ereignis)
        {
            tab_change ();
        }}
    );

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

        $ ('.tab-link') .click
        (
            Funktion (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');
            }}
        );
    }}

simonl
quelle
0

Ich habe verstanden, dass OP die Verwendung von JQuery sagte, aber Sie können einfach Vanilla JS verwenden, um dies zu tun:

document.querySelectorAll('ul.nav a.nav-link').forEach(link => {
    link.onclick = () => window.history.pushState(null, null, link.attributes.href.value);
});
RousseauAlexandre
quelle
-2

Dies behebt auch eine extrem undurchsichtige Registerkarte, die bei Verwendung von jquery und bootstrap nicht ausgelöst wird

<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>
Strahl
quelle
5
-1 Ich sehe nicht, wie diese Antwort den bereits vor 3 Monaten gegebenen Antworten mit genau demselben Code in der Antwort einen Wert hinzufügt. Daher meiner bescheidenen Meinung nach keine nützliche Antwort.
Nein,