Obtendo a localização de hash da URL e usando-a no jQuery

135

Eu gostaria de obter o valor após um hash no URL da página atual e poder aplicar isso em uma nova função ... por exemplo.

O URL pode ser

www.example.com/index.html#foo

E eu gostaria de usar isso em conjunto com o seguinte trecho de código

$('ul#foo:first').show();

Estou assumindo / esperando que exista alguma maneira de capturar isso e transformá-lo em uma variável que eu possa usar no segundo trecho de código.

Robbie White
fonte
8
Não tenho nenhum código para você, mas certifique-se de higienizar a entrada, pois isso parece adequado para a injeção de código.
Nate B
Entender que essa pergunta tem quase uma década 'ul#foo:first'não faz sentido, pois os IDs devem ser únicos, portanto, adicionar :firstao seletor é redundante, a menos que você esteja duplicando IDs inválidos. Observe que, mesmo uma década atrás, os IDs repetidos ainda eram inválidos.
J08691
Ainda estava errado há uma década
Douglas

Respostas:

280

Nota do editor: a abordagem abaixo tem sérias implicações de segurança e, dependendo da versão do jQuery que você está usando, pode expor seus usuários a ataques XSS. Para obter mais detalhes, consulte a discussão do possível ataque nos comentários sobre esta resposta ou nesta explicação sobre o Security Stack Exchange .

Você pode usar a location.hashpropriedade para obter o hash da página atual:

var hash = window.location.hash;
$('ul'+hash+':first').show();

Observe que essa propriedade já contém o #símbolo no início.

Na verdade, você não precisa do :firstpseudo-seletor, pois está usando o seletor de ID ; pressupõe-se que os IDs sejam únicos no DOM.

Caso deseje obter o hash de uma string de URL, você pode usar o String.substringmétodo:

var url = "http://example.com/file.htm#foo";
var hash = url.substring(url.indexOf('#')); // '#foo'

Conselho: Esteja ciente de que o usuário pode alterar o hash como ele deseja, injetando qualquer coisa no seu seletor; você deve verificar o hash antes de usá-lo.

CMS
fonte
30
Observe que os seletores jQuery podem ser usados ​​para executar o código javascript personalizado, portanto, o uso de hashes não autorizados é horrivelmente inseguro. Existe uma correção meia-boca para isso nas versões recentes do jQuery para seletores que contêm um # antes do código injetado, mas você ainda corre risco se remover a marca # do início de location.hash. Por exemplo. var hash = location.hash.slice(1); $('ul.item'+hash).show().append($('#content'));isso executará uma tag de script inserida no hash. É um bom hábito usar em $('body').find('ul'+hash+':first')vez de $('ul'+hash+':first').
1/12
40
Alguns navegadores retornam o símbolo de hash e outros não, por isso é mais seguro usar:var hash = location.hash.replace('#', '');
Tim
12
Alice administra um site, Bob o visita, autentica e recebe um cookie de sessão. (Pode passar algum tempo aqui, Bob pode até fechar o navegador.) Charlie envia um e-mail para Bob dizendo "confira este link legal!". Bob abre o link, que leva a um site controlado por Charlie. A página redireciona o navegador de Bob para uma página no site de Alice com uma carga útil de ataque no hash. A carga útil é executada e, como o navegador ainda se lembra dos cookies, ele pode apenas enviá-los para Charlie.
Tgr 25/07/12
2
@ Tgr, obrigado por elaborar e conectar os pontos. Este exemplo concreto me deixa (e espero que outros) mais inclinado à vigilância para manter as coisas seguras.
22812 Snapfractalpop
2
@ buffer: $(userInput)geralmente não é seguro porque $está sobrecarregado e pode procurar nós existentes ou criar novos, dependendo se a string contém <>caracteres. $(document).find(userInput)sempre procurará por nós existentes, para que seja menos perigoso. Dito isso, a melhor prática é sempre limpar a entrada do usuário, por exemplo, se você usar IDs alfanuméricos, verifique se é alfanumérico.
Tgr
35

location.hash não é seguro para o IE , no caso do IE (incluindo o IE9), se sua página contiver iframe, após a atualização manual do conteúdo do iframe obter o valor location.hash é antigo (valor para o carregamento da primeira página). enquanto o valor recuperado manual é diferente de location.hash, sempre o recupere através de document.URL

var hash = document.URL.substr(document.URL.indexOf('#')+1) 
Deepak Patil
fonte
7
Update: não document.URL não contém o valor hash no firefox 3.6 tão location.href é seguro var de hash = location.href.substr (location.href.indexOf ( '#') + 1)
Deepak Patil
4

Para quem procura uma solução javascript pura

 document.getElementById(location.hash.substring(1)).style.display = 'block'

Espero que isso poupe algum tempo.

Matas Vaitkevicius
fonte
3

Desde o jQuery 1.9, o :targetseletor corresponderá ao hash da URL. Então você poderia fazer:

$(":target").show(); // or $("ul:target").show();

O que selecionaria o elemento com o ID correspondente ao hash e o mostraria.

j08691
fonte
existe uma maneira de extrair o hash como uma seqüência de caracteres em vez de id de correspondência?
ina
@ina Você quer dizer obter o hash do jQuery :targetcomo uma string? Se sim, não acredito.
j08691 02/02
1

Eu sugeriria melhor cek primeiro se a página atual tiver um hash. Caso contrário, será undefined.

$(window).on('load', function(){        
    if( location.hash && location.hash.length ) {
       var hash = decodeURIComponent(location.hash.substr(1));
       $('ul'+hash+':first').show();;
    }       
});
Chetabahana
fonte
1

Estou usando isso para resolver as implicações de segurança observadas na resposta do @ CMS.

// example 1: www.example.com/index.html#foo

// load correct subpage from URL hash if it exists
$(window).on('load', function () {
    var hash = window.location.hash;
    if (hash) {
        hash = hash.replace('#',''); // strip the # at the beginning of the string
        hash = hash.replace(/([^a-z0-9]+)/gi, '-'); // strip all non-alphanumeric characters
        hash = '#' + hash; // hash now equals #foo with example 1

        // do stuff with hash
        $( 'ul' + hash + ':first' ).show();
        // etc...
    }
});
squarecandy
fonte