Você pode usar a navegação hash sem afetar o histórico?

100

Receio que seja impossível, mas existe uma maneira de alterar o valor hash de um URL sem deixar uma entrada no histórico do navegador e sem recarregar ? Ou faça o equivalente?

No que diz respeito às especificações, eu estava desenvolvendo uma navegação básica de hash ao longo das linhas de:

//hash nav -- works with js-tabs
var getHash = window.location.hash;
var hashPref = "tab-";
function useHash(newHash) {
    //set js-tab according to hash
    newHash = newHash.replace('#'+hashPref, '');
    $("#tabs li a[href='"+ newHash +"']").click();
}
function setHash(newHash) {
    //set hash according to js-tab
    window.location.hash = hashPref + newHash;

    //THIS IS WHERE I would like to REPLACE the location.hash
    //without a history entry

}
    // ... a lot of irrelavent tabs js and then....

    //make tabs work
    $("#tabs.js-tabs a").live("click", function() {
        var showMe = $(this).attr("href");
        $(showMe).show();
        setHash(showMe);
        return false;
    });
    //hash nav on ready .. if hash exists, execute
    if ( getHash ){
        useHash(getHash);
    }

Usando jQuery, obviamente. A ideia é que , neste caso específico 1) fazer o usuário voltar a cada mudança de guia poderia efetivamente 'quebrar o botão Voltar' acumulando referências desnecessárias e 2) não reter em qual guia ele está atualmente se clicar em atualizar é um aborrecimento.


fonte
Por que você deseja alterar o hash se não deseja manter o controle do histórico? : |
Ionuț Staicu
10
Porque na atualização, seria melhor apresentar ao usuário a guia em que ele estava, mas como ele pode estar alternando entre as guias, isso sobrecarregaria seu histórico com entradas desnecessariamente, tornando o botão Voltar realmente menos útil. Este é apenas um exemplo - pode ser para qualquer momento em que você precisar salvar um estado temporário, mas não quiser depender de cookies ou preencher o arquivo temporário do usuário com eles. Quando você atualiza, o conteúdo js é como você o deixou - você não saiu da página e não é um ponto de salto ou uma página psuedo, portanto, a entrada de histórico só pode interferir com o nav padrão.

Respostas:

95

location.replace("#hash_value_here");funcionou bem para mim até descobrir que não funciona no IOS Chrome. Nesse caso, use:

history.replaceState(undefined, undefined, "#hash_value")

history.replaceState () opera exatamente como history.pushState (), exceto que replaceState () modifica a entrada de histórico atual em vez de criar uma nova.

Lembre-se de guardar o #ou a última parte do url será alterada.

Lucia
fonte
3
Totalmente o caminho a seguir para navegadores modernos; esteja ciente do gerenciamento de histórico de sessão de suporte parcial .
Matt,
Estou confuso sobre como usar isso. Ainda devo usar window.location.hash = 'my-hash';seguido de history.replaceState(undefined, undefined, "#my-hash")?
Bram Vanroy
2
@BramVanroy Não, usar o último é suficiente.
Lucia de
2
A menos que você use: seletores de destino ... então as funções de histórico são inúteis, já que essa parte da especificação (interação de css com operações de histórico) parece não estar definida atualmente, e o estilo não é recomputado na substituição de histórico pela maioria / todos os navegadores.
morfos
@Luxiyalu, de que history.replaceStatedifere location.replace?
Pacerier,
99
location.replace("#hash_value_here"); 

O acima parece fazer o que você procura.

Matt
fonte
4
É isso. E se você tiver segmentos de uri, location.replace (window.location + "#hash") os preservará.
viradores de
7
Apoiando este método, muito mais limpo, gostaria que fosse marcada como a resposta correta.
joeellis
14
window.location.replace(('' + window.location).split('#')[0] + '#' + hash);apenas para atualizar o hash
johnstorm
1
Estou testando no Chrome 30 no Windows 8, se eu acessar o Chrome History e selecionar "More from this site" no meu url de teste, posso ver todos os hashes que foram adicionados com este método.
Alex Vang,
1
Esteja ciente de que location.replace ('# hash_value_here') altera apenas o fragmento hash e não o caminho, portanto, não aciona o carregamento da página .... Exceto quando o documento contém uma tag de base: <base href ="http://example.com/" /> Se contiver uma tag de base , então quando você usar o método replace com apenas um inicial "#hash_value_here", será como se você dissesse `location.replace (' example.com/#hash_value_here' ). Isso parece óbvio quando você lê aqui, mas é um problema quando você está em uma página com um fragmento de caminho e não percebe que a base está definida.
Tyler Kasten
6

Edit: Já se passaram alguns anos e os navegadores evoluíram.

A resposta de @Luxiyalu é o caminho a percorrer

- Resposta Antiga -

Eu também acho que é impossível (neste momento). Mas por que você precisa alterar o valor de hash se não vai usá-lo?

Acredito que o principal motivo pelo qual usamos o valor hash como programadores é para permitir que o usuário marque nossas páginas ou para salvar um estado no histórico do navegador. Se você não quiser fazer nada disso, basta salvar o estado em uma variável e trabalhar a partir daí.

Acho que o motivo de usar um hash é trabalhar com um valor que está fora de nosso controle. Se você não precisa disso, provavelmente significa que tem tudo sob seu controle, então apenas armazene o estado em uma variável e trabalhe com ele. (Eu gosto de me repetir)

Espero que isso ajude você. Talvez haja uma solução mais fácil para o seu problema.

ATUALIZAÇÃO: Que tal:

  1. Configure um primeiro hash e certifique-se de que ele seja salvo no histórico do navegador.
  2. Quando uma nova guia for selecionada, faça window.history.back(1), isso fará com que o histórico volte a partir do seu primeiro hash init.
  3. Agora que você definiu o novo hash, a tabulação fará apenas uma entrada no histórico.

Você provavelmente terá que usar alguns sinalizadores para saber se a entrada atual pode ser "excluída" voltando ou se você simplesmente pula o primeiro passo. E para ter certeza, que seu método de carregamento para o "hash" não execute, quando você força o history.back.

guzart
fonte
É muito possível que esteja faltando algo básico (exaustão é uma boa desculpa, vou continuar com isso), mas você está dizendo que posso definir uma variável que manterá seu valor alterado na recarga? Além de um biscoito? (Cookies parecem exageros, de alguma forma ...) Talvez isso não esteja claro. Usarei o valor de hash - especialmente no reload. Obrigado por responder!
Para esclarecer meu esclarecimento: se o usuário clicar em recarregar. É para isso que serve o hash. Ainda estou tentando evitar a recarga em seu uso normal (alterando / clicando nas guias).
Ok, então você usará alguns valores para informações após recarregar. Bem, infelizmente, o valor do hash será escolhido pelo histórico de alguns navegadores. Desculpe dizer isso, mas pela minha experiência, cookies são sua melhor aposta. Se você quiser algo que o histórico do navegador não detecte, mas retenha após recarregar, infelizmente, os cookies. Se o usuário estava clicando em um link, você poderia configurar o link para ser uma consulta ( ?mystate=greatness), embora não precise ser ajax, você poderia salvar informações para o javascript ler ao inicializar a solicitação.
guzart
Sim, o hash serve para salvar as informações do usuário após clicar em recarregar, mas o problema para a sua situação é que alguns navegadores salvam essas alterações no histórico, é assim que funcionam ... :(
guzart
Sim, acho que você está certo. Ah bem. (
-1

Você sempre pode criar um ouvinte de evento para capturar eventos de clique no hiperlink e na função de retorno de chamada colocar e.preventDefault (), que deve impedir o navegador de inseri-lo no histórico.

Ayman Farhat
fonte