Karty Bootstrap na Twitterze: przejdź do konkretnej karty na stronie Przeładuj stronę lub hiperłączu


358

Zajmuję się tworzeniem strony internetowej, w której korzystam z platformy Bootstrap Framework Twittera i jej kart Bootstrap JS . Działa świetnie, z wyjątkiem kilku drobnych problemów, z których jednym jest to, że nie wiem, jak przejść bezpośrednio do konkretnej karty z linku zewnętrznego. Na przykład:

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

powinien przejść odpowiednio do karty Strona główna i karty Notatki po kliknięciu linków ze strony zewnętrznej


49
szkoda, że ​​to nie było wbudowane!
Damon

5
To pytanie zostało również poruszone tutaj: github.com/twitter/bootstrap/issues/2415 (i ma tam kilka rozwiązań).
Ztyx,


1
Zaktualizowany link do problemu bootstrap to github.com/twbs/bootstrap/issues/2415
bmihelac 28.08.13

3
Wtyczka, która to rozwiązuje: github.com/timabell/jquery.stickytabs
Tim Abell

Odpowiedzi:


603

Oto moje rozwiązanie problemu, być może nieco spóźnione. Ale może pomóc innym:

// 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
Dodałbym jeszcze 1 dodatkową linię, window.scrollTo(0, 0);aby okno zawsze przewijało się do góry
Trung Lê

1
$ ('. nav-tabs a [href * = #' + url.split ('#') [1] + ']'). tab ('show'); // Z * jest bezpieczniejszy, ponieważ w przeciwnym razie pasuje tylko do pierwszego # ...
mattangriffel

1
Online, które działało dla mnie: window.location.hash && $ ('li a [href = "' + window.location.hash + '"]'). Tab ('show'). Trigger („click”);
Dean Meehan

10
Oto wersja demonstracyjna Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 i kod źródłowy
Zim

2
Po aktualizacji jQuery 1.11 od 1.09 dostaję ten błąd: Syntax error, unrecognized expression: .nav-tabs a[href=#tab-2]. Rozwiązane przy użyciu stackoverflow.com/questions/12131273/...
Pietro Z.

213

AKTUALIZACJA

W przypadku Bootstrap 3 zmień .on('shown', ...)na.on('shown.bs.tab', ....)


Jest to oparte na odpowiedzi @dubbe i tej zaakceptowanej odpowiedzi SO . Rozwiązuje problem z window.scrollTo(0,0)nieprawidłowym działaniem. Problem polega na tym, że po zastąpieniu skrótu adresu URL na zakładce przeglądarka przewinie ten skrót, ponieważ jest to element na stronie. Aby obejść ten problem, dodaj prefiks, aby skrót nie odwoływał się do rzeczywistego elementu strony

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

Przykład zastosowania

Jeśli masz tabulatory z id = "mytab", musisz umieścić swój link w następujący sposób:

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

1
Czy istnieje prosty sposób odwoływania się do zakładek, które znajdują się pod określoną kartą? Na mojej stronie jest pięć kart, a pod nimi kilka zakładek. Chciałbym, aby te zakładki były dostępne poza zakładką.
nize

@nize, jeśli utworzysz jsfiddle z tym, co próbujesz zrobić, postaram się rzucić okiem.
flynfish

1
Oto demonstracja Bootlpy dla Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 i kod źródłowy
Zim

W powyższym przykładzie brakuje podwójnych cudzysłowów na href. wiersz 5 powinien być:$('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
Ponyboy

Działa dla mnie z tym wyjątkiem, że musiałem usunąć ostatni ukośnik (przed #) z „yoursite.com/anotherpage/#tab_mytab”, w przeciwnym razie spowodowałoby to spustoszenie przy ładowaniu strony.
Alexander

52

możesz wywołać clickzdarzenie w odpowiednim zakładce:

$(document).ready(function(){

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

});

Dzięki za wskazówkę! Działa to świetnie z jednym małym problemem. Odświeżenie strony nie spowoduje przejścia do właściwej karty. Naciśnięcie Ctrl + F5 spowoduje. Zmodyfikowałem kod do następującego: `$ (dokument) .ready (function () {function getUrlVars () {var vars = {}; var parts = window.location.href.replace (/ [? &] + ([ ^ = &] +) = ([^ &] *) / gi, function (m, key, value) {vars [key] = value;}); return vars;} var action = getUrlVars () [„action” ]; if (action! = "") {$ ('a [href = "#' + action + '"]'). click ()};}); `
mraliks

44

Jest to ulepszona implementacja rozwiązania dubbe, która zapobiega przewijaniu.

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

Chociaż dostarczone rozwiązanie JavaScript może działać, poszedłem w nieco inny sposób, który nie wymaga dodatkowego JavaScript, ale wymaga logiki w twoim widoku. Tworzysz link ze standardowym parametrem adresu URL, takim jak:

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

Następnie po prostu wykrywasz wartość activeTab, aby napisać „class =" active ”w odpowiednim polu <li>

Pseudokod (zaimplementuj odpowiednio w swoim języku). Uwaga Ustawiłem kartę „home” jako domyślną aktywną, jeśli w tym przykładzie nie podano parametru.

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

Wolę twoje rozwiązanie od rozwiązania JS z jednego prostego powodu: lokalizacja JS. Skrót przeskakuje do identyfikatora, który powoduje, że pozycja kursora przesuwa się w górę i w dół.
Trung Lê

Wolę to rozwiązanie. W rzeczywistości utworzyłem nowe trasy dla kart i ponownie wygenerowałem widok, ustawiając odpowiednio klasę aktywną. Pozwala to uniknąć problemów związanych ze zmianą rozmiaru strony, mieszaniem adresów URL i przewijaniem strony.
Vijay Meena

10

Nie jestem wielkim fanem if ... else; więc podjąłem prostsze podejście.

$(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. Wybierz domyślną kartę (zwykle pierwszą)
  2. Przełącz na tab (jeśli taki element jest rzeczywiście obecny; niech jQuery go obsłuży); Nic się nie dzieje, jeśli podano nieprawidłowy skrót
  3. [Opcjonalnie] Zaktualizuj skrót, jeśli ręcznie wybierzesz inną kartę

Nie adresuje przewijania do żądanego skrótu; ale powinien ?



8

Działa to w Bootstrap 3 i poprawia 2 najlepsze odpowiedzi dubbe i flynfish, integrując również odpowiedź GarciaWebDev (która pozwala na parametry adresu URL po skrócie i pochodzi bezpośrednio od autorów Bootstrap na trackerze problemów github):

// 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
to nie działa w Bootstrap 3, 'shown'powinno być zgodne 'shown.bs.tab'z dokumentami: getbootstrap.com/javascript/#tabs-events . Jestem zaskoczony, dlaczego, ale kiedy próbowałem edytować Twój post, został odrzucony ...
YPCrumble

6

Ten kod wybiera odpowiednią kartę w zależności od # skrótu i ​​dodaje prawy # skrót po kliknięciu karty. (używa jquery)

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

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

upewnij się, że umieściłeś to po załadowaniu jquery. Umieszczałem go na środku strony (było to łatwe miejsce do wstawienia go do testowania) i nie działało. Umieszczenie go po załadowaniu jquery działa świetnie.
Ron

6

Opierając się na rozwiązaniu Demircana Celebi; Chciałem otworzyć kartę podczas modyfikowania adresu URL i otwierać kartę bez konieczności ponownego ładowania strony z serwera.

<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 rozwiązanie, którego używam dla zagnieżdżonych kart:

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

dzieci powinny mieć class = "nested"


5

Wymyśliłem rozwiązanie, które używa skrótu URL lub localStorage w zależności od dostępności tego ostatniego z poniższym kodem:

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

Wypróbowałem kilka sposobów omówionych powyżej i skończyłem na działającym rozwiązaniu, po prostu skopiuj i wklej w edytorze, aby spróbować. Aby przetestować, po prostu zmień skrót na skrzynkę odbiorczą, skrzynkę nadawczą, wpisz adres URL i naciśnij klawisz Enter.

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

Mam nadzieję, że pozwoli to zaoszczędzić Twój czas.


3

Oto, co zrobiłem, naprawdę proste i pod warunkiem, że linki do kart mają powiązany identyfikator, możesz pobrać atrybut href i przekazać go do funkcji wyświetlającej zawartość karty:

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

Następnie w swoim adresie URL możesz dodać skrót jako coś w stylu: # tab_tab1, część „tab_” jest usuwana z samego skrótu, więc identyfikator rzeczywistego łącza do karty w zakładkach nawigacyjnych (tabid1) jest następnie umieszczany, więc twoja URL wyglądałby mniej więcej tak: www.mydomain.com/index.php#tab_tabid1.

Działa to idealnie dla mnie i mam nadzieję, że pomoże komuś innemu :-)


2

To jest moje rozwiązanie do obsługi zagnieżdżonych kart. Właśnie dodałem funkcję sprawdzania, czy aktywna karta ma kartę nadrzędną do aktywacji. To jest funkcja:

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

I można go tak nazwać (w oparciu o rozwiązanie @ 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);
});

To rozwiązanie działa w tej chwili dla mnie całkiem dobrze. Mam nadzieję, że może to być przydatne dla kogoś innego;)


2

Musiałem zmodyfikować kilka bitów, aby to działało dla mnie. Korzystam z Bootstrap 3 i 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);
});

Świetna odpowiedź, tyle że musiałem zastąpić „!” przedrostek z „tab_”. W przeciwnym razie działało idealnie.
koziez

2

Po prostu wstaw ten kod na swojej stronie:

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

Właśnie miałem ten problem, ale potrzebowałem obsługiwać wiele poziomów kart. Kod jest raczej brzydki (patrz komentarze), ale spełnia swoje zadanie: https://gist.github.com/JensRantil/4721860 Mam nadzieję, że ktoś inny uzna go za przydatny (i może zaproponować lepsze rozwiązania!).


1

Łącząc fragmenty z innych odpowiedzi, oto rozwiązanie, które może otworzyć wiele poziomów zagnieżdżonych kart:

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

działa tylko na 2 poziomach zagnieżdżenia, 3. poziom powoduje problemy.
Nicholas Hamilton

Właśnie przetestowałem to na trzech poziomach kart i wydaje mi się, że to działa. Czy jesteś pewien, że to nie jest problem z twoją implementacją? Jakiego „problemu” doświadczasz?
cweston

Każda karta na 1. poziomie i 2. poziomie działa dobrze, jednak na 3. poziomie, podczas odświeżania strony (lub przesyłania formularza), gdy strona ponownie się otwiera, fokus jest przypisywany do pierwszej karty na 2. poziomie.
Nicholas Hamilton

Więc działa poprawnie (w moim kodzie było trochę literówki), jednak po korekcie literówek, tylko z $('.nav-tabs li a').click( function(e) { history.pushState( null, null, $(this).attr('href') );});javascript nad twoim kodem.
Nicholas Hamilton

1

Jeśli ma to znaczenie dla każdego, poniższy kod jest mały i działa bez zarzutu, aby uzyskać pojedynczą wartość skrótu z adresu URL i pokazać, że:

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

robi to, pobiera identyfikator i uruchamia zdarzenie click. Prosty.


0

Robię coś takiego dla linków z ajax #!#(np. / Test.com #! # Test3), ale możesz to modyfikować cokolwiek chcesz

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

Przykład z prostą stroną na Github tutaj


0

Wiem, że ten wątek jest bardzo stary, ale zostawię tutaj własną implementację:

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

Zauważ, że używam nav-przedrostka klasy do nawigacji linków.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.