Guias de inicialização do Twitter: Vá para a guia específica na página Atualizar ou hiperlink

358

Estou desenvolvendo uma página da Web na qual estou usando o Bootstrap Framework do Twitter e seu JS de Bootstrap Tabs . Funciona muito bem, exceto por alguns problemas menores, um dos quais é que eu não sei como ir diretamente para uma guia específica a partir de um link externo. Por exemplo:

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

deve ir para a guia Início e a guia Notas, respectivamente, quando clicadas nos links de uma página externa

mraliks
fonte
49
gostaria que isso fosse construído!
Damon
5
Esta questão também foi levantada aqui: github.com/twitter/bootstrap/issues/2415 (e tem algumas soluções lá).
Ztyx
isso ajudou-me -> stackoverflow.com/questions/12131273/… #
JGilmartin
11
O link atualizado para a questão do bootstrap é github.com/twbs/bootstrap/issues/2415
#
3
Plugin que corrige isso: github.com/timabell/jquery.stickytabs
Tim Abell

Respostas:

603

Aqui está a minha solução para o problema, talvez um pouco tarde. Mas talvez ajude outras pessoas:

// 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
fonte
83
Eu adicionaria uma linha mais adicional window.scrollTo(0, 0);para garantir que a janela sempre vá até o topo
Trung Lê
11
$ ('. nav-tabs a [href * = #' + url.split ('#') [1] + ']'). tab ('show'); // Com um * é mais seguro, pois caso contrário, corresponde apenas a primeira # ...
mattangriffel
11
On-line que funcionou para mim: window.location.hash && $ ('li a [href = "' + window.location.hash + '"]'). Tab ('show'). Trigger ("click");
31914 Dean Meehan
10
Aqui está uma demonstração para Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 eo código-fonte
Zim
2
Depois jquery upgrade para 1,11 de 1,09 eu recebo este erro: Syntax error, unrecognized expression: .nav-tabs a[href=#tab-2]. Resolvido usando stackoverflow.com/questions/12131273/…
Pietro Z.
213

ATUALIZAR

Para o Bootstrap 3, altere .on('shown', ...)para.on('shown.bs.tab', ....)


Isso é baseado na resposta @dubbe e esta resposta SO aceita . Ele lida com o problema window.scrollTo(0,0)sem funcionar corretamente. O problema é que, quando você substitui o hash do URL na guia mostrada, o navegador irá rolar para esse hash, já que é um elemento na página. Para contornar isso, adicione um prefixo para que o hash não faça referência a um elemento da página real

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

Exemplo de uso

Se você tiver um painel de tabulação com id = "mytab", precisará colocar seu link assim:

<a href="yoursite.com/#tab_mytab">Go to Specific Tab </a>
peixe voador
fonte
11
Haveria uma maneira simples de fazer referência aos favoritos localizados em uma guia específica? Tenho cinco guias na minha página e, nessas, tenho vários favoritos. O que eu gostaria é tornar esses favoritos vinculáveis ​​de fora da guia.
nize
@nize se você criar um jsfiddle com o que está tentando fazer, tentarei dar uma olhada.
flynfish
11
Aqui está uma demonstração Bootlpy para Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 eo código-fonte
Zim
O exemplo acima está faltando aspas duplas no href. a linha 5 deve ser:$('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
Ponyboy 23/06
Funciona para mim, exceto que eu tive que remover a última barra (antes do #) em 'yoursite.com/anotherpage/#tab_mytab', caso contrário, isso causou estragos no carregamento da página.
1148 Alexander Alexander
52

você pode acionar um clickevento no link da guia correspondente:

$(document).ready(function(){

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

});
Marian Theisen
fonte
Obrigado pela dica! Isso funcionou muito bem com um pequeno problema. A atualização da página não levaria para a guia correta. Pressionar Ctrl + F5 faria. Modifiquei o código para o seguinte: `$ (document) .ready (function () {function getUrlVars () {var vars = {}; var partes = window.location.href.replace (/ [? &] + ([ ^ = &] +) = ([^ &] *) / gi, função (m, chave, valor) {vars [chave] = valor;}); retornar vars;} var action = getUrlVars () ["action" ]; if (action! = "") {$ ('a [href = "#' + ação + '"]'). click ()};}); `
mraliks
44

Esta é uma implementação aprimorada da solução do dubbe, que impede a rolagem.

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

Embora a solução JavaScript fornecida possa funcionar, eu segui uma maneira um pouco diferente que não requer JavaScript adicional, mas exige lógica na sua visão. Você cria um link com um parâmetro de URL padrão, como:

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

Então você simplesmente detecta o valor de activeTab para escrever 'class = "active"' no apropriado <li>

Pseudocódigo (implemente de acordo com o seu idioma). Observe que eu configurei a guia 'home' como um padrão ativo se nenhum parâmetro for fornecido neste exemplo.

$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>
Pedro
fonte
Prefiro sua solução à solução JS devido a uma simples razão: JS location.hash saltaria para o ID, o que fará com que a posição do cursor suba e desça.
Trung Lê
Eu prefiro esta solução. Na verdade, eu criei novas rotas para guias e gerenciei a visualização definindo a classe ativa de acordo. Isso evita dores de cabeça com redimensionamento de página, hash de URL e rolagem de página todos juntos.
Vijay Meena
10

Eu não sou um grande fã de se ... mais; então, adotei uma abordagem mais simples.

$(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. Escolha uma guia padrão (geralmente a primeira)
  2. Alterne para tab (se esse elemento estiver realmente presente; deixe o jQuery manipulá-lo); Nada acontece se um hash errado for especificado
  3. [Opcional] Atualize o hash se outra guia for escolhida manualmente

Não endereça a rolagem para o hash solicitado; mas deveria ?

visitasb
fonte
8

Isso funciona no Bootstrap 3 e aprimora as 2 principais respostas de dubbe e flynfish, integrando também a resposta do GarciaWebDev (que permite parâmetros de URL após o hash e é diretamente dos autores do Bootstrap no rastreador de problemas do 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
fonte
11
isso não funciona no Bootstrap 3, 'shown'deve estar de 'shown.bs.tab'acordo com os documentos: getbootstrap.com/javascript/#tabs-events . Estou confuso quanto ao porquê, mas quando eu tentei editar o seu post-it foi rejeitado ...
YPCrumble
6

Esse código seleciona a guia direita, dependendo do #hash, e adiciona o #hash direito quando uma guia é clicada. (isso usa jquery)

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

ou em 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
fonte
certifique-se de colocar isso depois que o jquery for carregado. Eu estava no meio de uma página (era um local fácil para inseri-lo para teste) e não funcionou. Colocá-lo depois de carregar o jquery funciona muito bem.
Ron
6

Aproveitando a solução do Demircan Celebi; Queria que a guia fosse aberta ao modificar o URL e a guia aberta sem precisar recarregar a página do servidor.

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

Solução @flynfish + @Ztyx que eu uso para guias aninhadas:

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

as crianças devem ter class = "aninhado"

Artem Kashin
fonte
5

Eu vim com uma solução que usa o URL hash ou localStorage, dependendo da disponibilidade do último com o código abaixo:

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

Eu sugiro que você use o código fornecido pelos autores do Bootstrap no rastreador de problemas no GitHub :

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

Você pode encontrar no link do problema mais informações sobre por que eles não escolheram apoiar isso.

Alejandro García Iglesias
fonte
4

Tentei algumas maneiras discutidas acima e acabamos com a seguinte solução de trabalho, basta copiar e colar no seu editor para tentar. Para testar, basta alterar o hash para caixa de entrada, caixa de saída, redigir em url e pressionar a tecla 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>

Espero que isso economize seu tempo.

Abhimanyu
fonte
3

Aqui está o que eu fiz, realmente simples, e desde que os links da sua guia tenham um ID associado a eles, você pode obter o atributo href e passar isso para a função que mostra o conteúdo da guia:

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

Em seu URL, você pode adicionar o hash da seguinte maneira: # tab_tab1, a parte 'tab_' é removida do próprio hash, para que o ID do link da guia real nas guias de navegação (tabid1) seja colocado depois disso, para que seu url seria algo como: www.mydomain.com/index.php#tab_tabid1.

Isso funciona perfeito para mim e espero que ajude outra pessoa :-)

Derek Buntin
fonte
2

Esta é a minha solução para lidar com guias aninhadas. Acabei de adicionar uma função para verificar se a guia ativa tem uma guia pai a ser ativada. Esta é a função:

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

E pode ser chamado assim (com base na solução do @ 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);
});

Esta solução funciona muito bem para mim no momento. Espero que isso possa ser útil para outra pessoa;)

Stefano Marra
fonte
2

Eu tive que modificar alguns bits para que isso funcionasse para mim. Estou usando o Bootstrap 3 e o 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
fonte
Ótima resposta, exceto que eu tive que substituir o "!" prefixo com "tab_". Caso contrário, funcionou perfeitamente.
koziez
2

Basta inserir este código na sua página:

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

Acabei de ter esse problema, mas precisava lidar com vários níveis de guia. O código é bastante feio (veja os comentários), mas faz o seu trabalho: https://gist.github.com/JensRantil/4721860 Espero que alguém o ache útil (e fique à vontade para propor melhores soluções!).

Ztyx
fonte
1

Combinando partes de outras respostas, aqui está uma solução que pode abrir muitos níveis de guias aninhadas:

// 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
fonte
só funciona em 2 níveis de aninhamento, o terceiro nível causa problemas.
Nicholas Hamilton
Acabei de testar isso em três níveis de guias, e parece estar funcionando para mim. Tem certeza de que isso não é um problema com sua implementação? Qual "problema" você está enfrentando?
cweston 22/02
Qualquer guia no 1º e 2º nível funciona bem, no entanto, no 3º nível, ao atualizar a página (ou ao enviar o formulário), quando a página é reaberta, o foco é dado à primeira guia no 2º nível.
Nicholas Hamilton
Então, funcionou bem (houve um erro de digitação menor no meu código), no entanto, após a correção do erro de digitação, apenas $('.nav-tabs li a').click( function(e) { history.pushState( null, null, $(this).attr('href') );});no javascript acima do seu código.
Nicholas Hamilton
1

Se isso for importante para alguém, o código a seguir é pequeno e funciona perfeitamente, para obter um único valor de hash da URL e mostrar que:

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

o que ele faz é recuperar o ID e disparar o evento click. Simples.

Sam
fonte
0

Eu faço sth assim para links com ajax #!#(por exemplo, / test.com #! # Test3), mas você pode modificá-lo como quiser

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

Exemplo com página simples no Github aqui

eudaimonia
fonte
0

Eu sei que este segmento é muito antigo, mas vou deixar aqui minha própria implementação:

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

Observe que estou usando um nav-prefixo de classe para navegar nos links.

Renan Coelho
fonte