Twitter-Bootstrap-Registerkarten: Gehen Sie auf Seite Reload oder Hyperlink zur Registerkarte Spezifisch


358

Ich entwickle eine Webseite, auf der ich das Bootstrap Framework von Twitter und dessen Bootstrap Tabs JS verwende . Es funktioniert großartig, bis auf ein paar kleinere Probleme, von denen eines ist, dass ich nicht weiß, wie ich von einem externen Link direkt zu einem bestimmten Tab gehe. Zum Beispiel:

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

sollte auf die Registerkarte Startseite und die Registerkarte Notizen gehen, wenn Sie auf die Links einer externen Seite klicken


49
Ich wünschte, dies wäre eingebaut!
Damon

5
Diese Frage wurde auch hier gestellt: github.com/twitter/bootstrap/issues/2415 (und hat dort einige Lösungen).
Ztyx


1
Der aktualisierte Link zum Bootstrap-Problem lautet github.com/twbs/bootstrap/issues/2415
bmihelac

3

Antworten:


603

Hier ist meine Lösung für das Problem, vielleicht etwas spät. Aber es könnte vielleicht anderen helfen:

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

83
Ich würde 1 weitere Zeile hinzufügen window.scrollTo(0, 0);, um sicherzustellen, dass das Fenster immer nach oben
rollt

1
$ ('. nav-tabs a [href * = #' + url.split ('#') [1] + ']'). tab ('show'); // Mit einem * ist sicherer, da es sonst nur mit dem ersten # ...
mattangriffel

1
Online, das für mich funktioniert hat: window.location.hash && $ ('li a [href = "' + window.location.hash + '"]'). Tab ('show'). Trigger ("click");
Dean Meehan

10
Hier ist eine Demo für Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 und der Quellcode
Zim

2
Nach dem Upgrade von jquery auf 1.11 von 1.09 erhalte ich folgende Fehlermeldung : Syntax error, unrecognized expression: .nav-tabs a[href=#tab-2]. Gelöst mit stackoverflow.com/questions/12131273/…
Pietro Z.

213

AKTUALISIEREN

Wechseln Sie für Bootstrap 3 .on('shown', ...)zu.on('shown.bs.tab', ....)


Dies basiert auf der Antwort von @dubbe und dieser SO akzeptierten Antwort . Es behebt das Problem, dass es window.scrollTo(0,0)nicht richtig funktioniert. Das Problem ist, dass der Browser beim Ersetzen des URL-Hash auf der angezeigten Registerkarte zu diesem Hash blättert, da er ein Element auf der Seite ist. Um dies zu umgehen, fügen Sie ein Präfix hinzu, damit der Hash nicht auf ein tatsächliches Seitenelement verweist

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

Anwendungsbeispiel

Wenn Sie einen Tab-Bereich mit id = "mytab" haben, müssen Sie Ihren Link wie folgt einfügen:

<a href="yoursite.com/#tab_mytab">Go to Specific Tab </a>

1
Gibt es eine einfache Möglichkeit, auf Lesezeichen zu verweisen, die sich unter einer bestimmten Registerkarte befinden? Ich habe fünf Registerkarten auf meiner Seite und unter diesen habe ich eine Reihe von Lesezeichen. Was ich möchte, ist, diese Lesezeichen von außerhalb der Registerkarte verknüpfbar zu machen.
nize

@nize Wenn Sie eine jsfiddle mit dem erstellen, was Sie versuchen, werde ich versuchen, einen Blick darauf zu werfen.
Flynfish

1
Hier ist eine Bootlpy-Demo für Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 und der Quellcode
Zim

Im obigen Beispiel fehlen die doppelten Anführungszeichen auf der href. Zeile 5 sollte sein:$('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
Ponyboy

Funktioniert für mich mit der Ausnahme, dass ich den letzten Schrägstrich (vor dem #) in 'yoursite.com/anotherpage/#tab_mytab' entfernen musste, da er sonst beim Laden der Seite Chaos verursachte.
Alexander

52

Sie können ein clickEreignis auf dem entsprechenden Tab-Link auslösen :

$(document).ready(function(){

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

});

Danke für den Tipp! Dies funktionierte hervorragend mit einem kleinen Problem. Wenn Sie die Seite aktualisieren, wird sie nicht auf die richtige Registerkarte verschoben. Strg + F5 drücken würde. Ich habe den Code wie folgt geändert: `$ (document) .ready (function () {function getUrlVars () {var vars = {}; var parts = window.location.href.replace (/ [? &] + ([) ^ = &] +) = ([^ &] *) / gi, Funktion (m, Schlüssel, Wert) {vars [Schlüssel] = Wert;}); Rückgabe vars;} var action = getUrlVars () ["Aktion" ]; if (action! = "") {$ ('a [href = "#' + action + '"]'). click ()};}); `
mraliks

44

Dies ist eine verbesserte Implementierung der Dubbe-Lösung, die das Scrollen verhindert.

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

21

Während die bereitgestellte JavaScript-Lösung möglicherweise funktioniert, bin ich einen etwas anderen Weg gegangen, der kein zusätzliches JavaScript erfordert, aber Ihrer Ansicht nach Logik erfordert. Sie erstellen einen Link mit einem Standard-URL-Parameter wie:

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

Dann erkennen Sie einfach den Wert von activeTab, um 'class = "active"' in das entsprechende Feld zu schreiben <li>

Pseudocode (entsprechend in Ihrer Sprache implementieren). Hinweis: Ich habe die Registerkarte "Home" als Standard aktiviert, wenn in diesem Beispiel kein Parameter angegeben ist.

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

Ich bevorzuge Ihre Lösung gegenüber der JS-Lösung aus einem einfachen Grund: JS location.hash würde zur ID springen, wodurch die Position des Cursors nach oben und unten bewegt wird.
Trung Lê

Ich bevorzuge diese Lösung. Tatsächlich habe ich neue Routen für Registerkarten erstellt und die Ansicht neu generiert, indem ich die aktive Klasse entsprechend festgelegt habe. Dies vermeidet Kopfschmerzen beim Ändern der Seitengröße, beim URL-Hash und beim Scrollen von Seiten.
Vijay Meena

10

Ich bin kein großer Fan von wenn ... sonst; Also habe ich einen einfacheren Ansatz gewählt.

$(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. Wählen Sie eine Standardregisterkarte (normalerweise die erste).
  2. Wechseln Sie zur Registerkarte (wenn ein solches Element tatsächlich vorhanden ist; lassen Sie jQuery damit umgehen); Nichts passiert, wenn ein falscher Hash angegeben wird
  3. [Optional] Aktualisieren Sie den Hash, wenn eine andere Registerkarte manuell ausgewählt wird

Adressiert das Scrollen zum angeforderten Hash nicht. sollte aber es?



8

Dies funktioniert in Bootstrap 3 und verbessert die beiden Top-Antworten von Dubbe und Flynfish, indem auch die Antwort von GarciaWebDev integriert wird (die URL-Parameter nach dem Hash zulässt und direkt von Bootstrap-Autoren auf dem Github-Issue-Tracker stammt):

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

1
Dies funktioniert nicht in Bootstrap 3, 'shown'sollte 'shown.bs.tab'gemäß den folgenden Dokumenten erfolgen: getbootstrap.com/javascript/#tabs-events . Ich bin verblüfft, warum, aber als ich versuchte, Ihren Beitrag zu bearbeiten, wurde er abgelehnt ...
YPCrumble

6

Dieser Code wählt die rechte Registerkarte abhängig vom #hash aus und fügt die rechte #hash hinzu, wenn auf eine Registerkarte geklickt wird. (dies verwendet 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)

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

Stellen Sie sicher, dass Sie dies setzen, nachdem jquery geladen wurde. Ich habe es in die Mitte einer Seite gestellt (es war ein einfacher Ort, um es zum Testen einzufügen) und es hat nicht funktioniert. Das Setzen nach dem Laden von jquery funktioniert hervorragend.
Ron

6

Aufbauend auf der Lösung von Demircan Celebi; Ich wollte, dass die Registerkarte geöffnet wird, wenn die URL geändert und die Registerkarte geöffnet wird, ohne dass die Seite vom Server neu geladen werden muss.

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


5

@ flynfish + @ Ztyx-Lösung, die ich für verschachtelte Registerkarten verwende:

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

Kinder sollten class = "verschachtelt" haben


5

Ich habe eine Lösung gefunden, die den URL-Hash oder localStorage verwendet, abhängig von der Verfügbarkeit des letzteren mit dem folgenden 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');
    }
});

4

Ich würde vorschlagen, dass Sie den von Bootstrap-Autoren bereitgestellten Code für ihren Issue-Tracker auf GitHub verwenden :

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

Unter dem Link zum Problem finden Sie weitere Informationen darüber, warum sie dies nicht unterstützt haben.


4

Probieren Sie einige der oben beschriebenen Möglichkeiten aus und erhalten Sie die folgende funktionierende Lösung. Kopieren Sie sie einfach und fügen Sie sie in Ihren Editor ein, um es zu versuchen. Zum Testen ändern Sie einfach den Hash in Posteingang, Postausgang, verfassen die URL und drücken die Eingabetaste.

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

Hoffe das spart deine Zeit.


3

Hier ist, was ich getan habe, ganz einfach, und vorausgesetzt, Ihren Tab-Links ist eine ID zugeordnet, können Sie das href-Attribut abrufen und dieses an die Funktion übergeben, die den Tab-Inhalt anzeigt:

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

Dann können Sie in Ihrer URL den Hash wie folgt hinzufügen: # tab_tab1, der Teil 'tab_' wird aus dem Hash selbst entfernt, sodass die ID des tatsächlichen Tab-Links in den Navigations-Tabs (tabid1) danach platziert wird Die URL würde ungefähr so ​​aussehen: www.mydomain.com/index.php#tab_tabid1.

Das funktioniert perfekt für mich und hoffe es hilft jemand anderem :-)


2

Dies ist meine Lösung für verschachtelte Registerkarten. Ich habe gerade eine Funktion hinzugefügt, um zu überprüfen, ob auf der aktiven Registerkarte eine übergeordnete Registerkarte aktiviert werden muss. Dies ist die Funktion:

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

Und kann so aufgerufen werden (basierend auf der Lösung von @ 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);
});

Diese Lösung funktioniert im Moment ziemlich gut für mich. Hoffe das kann für jemand anderen nützlich sein;)


2

Ich musste einige Bits modifizieren, damit dies für mich funktioniert. Ich verwende Bootstrap 3 und 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);
});

Tolle Antwort, außer dass ich das "!" Präfix mit "tab_". Ansonsten hat es perfekt funktioniert.
Koziez

2

Fügen Sie einfach diesen Code auf Ihrer Seite ein:

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


1

Ich hatte gerade dieses Problem, musste aber mehrere Registerkartenebenen behandeln. Der Code ist ziemlich hässlich (siehe Kommentare), macht aber seinen Job: https://gist.github.com/JensRantil/4721860 Hoffentlich findet ihn jemand anderes nützlich (und kann gerne bessere Lösungen vorschlagen!).


1

Hier ist eine Lösung, die Peices aus anderen Antworten kombiniert und viele Ebenen verschachtelter Registerkarten öffnen kann:

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

funktioniert nur auf 2 Verschachtelungsebenen, die 3. Ebene verursacht Probleme.
Nicholas Hamilton

Ich habe dies gerade anhand von drei Registerkarten getestet, und es scheint für mich zu funktionieren. Sind Sie sicher, dass dies kein Problem mit Ihrer Implementierung ist? Welches "Problem" haben Sie?
Weston

Jede Registerkarte in der 1. und 2. Ebene funktioniert einwandfrei. In der 3. Ebene wird jedoch beim Aktualisieren der Seite (oder beim Senden des Formulars) beim erneuten Öffnen der Seite der Fokus auf die erste Registerkarte in der 2. Ebene gelegt.
Nicholas Hamilton

Also hat es funktioniert (es gab einen kleinen Tippfehler in meinem Code), jedoch nach der Tippfehlerkorrektur, nur mit $('.nav-tabs li a').click( function(e) { history.pushState( null, null, $(this).attr('href') );});im Javascript über Ihrem Code.
Nicholas Hamilton

1

Wenn es für jemanden wichtig ist, ist der folgende Code klein und funktioniert einwandfrei, um einen einzelnen Hash-Wert von der URL zu erhalten und Folgendes zu zeigen:

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

Es ruft die ID ab und löst das Klickereignis aus. Einfach.


0

Ich mache etw so für Links mit Ajax #!#(zB / test.com #! # Test3), aber Sie können es ändern, was Sie wollen

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

Beispiel mit einfacher Seite auf Github hier


0

Ich weiß, dass dieser Thread sehr alt ist, aber ich werde hier meine eigene Implementierung belassen:

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

Beachten Sie, dass ich ein nav-Klassenpräfix für Navigationslinks verwende.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.