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

mraliks
źródło
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,
pomogło mi to -> stackoverflow.com/questions/12131273/…
JGilmartin
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;
})
dubbe
źródło
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>
mucha
źródło
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()
  }

});
Marian Theisen
źródło
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
    }
})
Demircan Celebi
źródło
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>
Piotr
źródło
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 ?

odwiedzinb
źródło
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);
});
greggdavis
źródło
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);
    });
});
Sucrenoir
źródło
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>
Gavin
źródło
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"

Artem Kashin
źródło
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');
    }
});
Vaibhav
źródło
4

Sugeruję użycie kodu dostarczonego przez autorów Bootstrap w narzędziu do śledzenia problemów na GitHub :

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

W linku do problemu można znaleźć więcej informacji o tym, dlaczego nie zdecydowali się go obsługiwać.

Alejandro García Iglesias
źródło
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.

Abhimanyu
źródło
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 :-)

Derek Buntin
źródło
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;)

Stefano Marra
źródło
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);
});
ruifn
źródło
Ś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);
  });
});

Amin Gholibeigian
źródło
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!).

Ztyx
źródło
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');
}
Cweston
źródło
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.

Sam
źródło
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

eudaimonia
źródło
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.

Renan Coelho
źródło