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

mraliks
quelle
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
das hat mir geholfen -> stackoverflow.com/questions/12131273/…
JGilmartin
1
Der aktualisierte Link zum Bootstrap-Problem lautet github.com/twbs/bootstrap/issues/2415
bmihelac
3
Plugin, das dies behebt: github.com/timabell/jquery.stickytabs
Tim Abell

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;
})
Dubbe
quelle
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>
Flynfish
quelle
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()
  }

});
Marian Theisen
quelle
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
    }
})
Demircan Celebi
quelle
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>
Peter
quelle
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?

Visitsb
quelle
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);
});
greggdavis
quelle
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);
    });
});
Sucrenoir
quelle
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>
Gavin
quelle
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

Artem Kashin
quelle
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');
    }
});
Vaibhav
quelle
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.

Alejandro García Iglesias
quelle
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.

Abhimanyu
quelle
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 :-)

Derek Buntin
quelle
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;)

Stefano Marra
quelle
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);
});
ruifn
quelle
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);
  });
});

Amin Gholibeigian
quelle
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!).

Ztyx
quelle
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');
}
cweston
quelle
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.

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

Eudaimonia
quelle
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.

Renan Coelho
quelle