Obtenir l'emplacement de hachage de l'URL et l'utiliser dans jQuery

135

J'aimerais obtenir la valeur après un hachage dans l'URL de la page actuelle et ensuite pouvoir l'appliquer dans une nouvelle fonction ... par exemple.

L'URL peut être

www.example.com/index.html#foo

Et je voudrais utiliser ceci en conjonction avec le morceau de code suivant

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

Je suppose / j'espère qu'il existe un moyen de saisir cela et de le transformer en une variable que je peux ensuite utiliser dans le deuxième morceau de code.

Robbie White
la source
8
Je n'ai pas de code pour vous, mais vous devez vous assurer de nettoyer l'entrée, car cela semble mûr pour l'injection de code.
Nate B
Comprendre que cette question a presque dix ans 'ul#foo:first'n'a pas de sens puisque les identifiants doivent être uniques, donc l'ajout :firstau sélecteur est redondant, à moins que vous ne dupliquiez des identifiants invalides. Notez qu'il y a même une décennie, les ID répétés n'étaient toujours pas valides.
j08691
Toujours eu tort il y a dix ans
Douglas

Réponses:

280

Note de l'éditeur: l'approche ci-dessous a de graves implications en matière de sécurité et, selon la version de jQuery que vous utilisez, peut exposer vos utilisateurs à des attaques XSS. Pour plus de détails, consultez la discussion sur l'attaque possible dans les commentaires sur cette réponse ou cette explication sur Security Stack Exchange .

Vous pouvez utiliser la location.hashpropriété pour récupérer le hachage de la page actuelle:

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

Notez que cette propriété contient déjà le #symbole au début.

En fait, vous n'avez pas besoin du :firstpseudo-sélecteur puisque vous utilisez le sélecteur d'ID , on suppose que les ID sont uniques dans le DOM.

Si vous souhaitez obtenir le hachage à partir d'une chaîne d'URL, vous pouvez utiliser la String.substringméthode:

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

Conseil: sachez que l'utilisateur peut modifier le hachage comme il le souhaite, en injectant n'importe quoi dans votre sélecteur, vous devez vérifier le hachage avant de l'utiliser.

CMS
la source
30
Notez que les sélecteurs jQuery peuvent être utilisés pour exécuter du code javascript personnalisé, donc utiliser des hachages non désinfectés est horriblement, horriblement dangereux. Il existe un correctif à moitié assed pour cela dans les versions récentes de jQuery pour les sélecteurs qui contiennent un # avant le code injecté, mais vous courez toujours un risque si vous supprimez la marque # du début de location.hash. Par exemple. var hash = location.hash.slice(1); $('ul.item'+hash).show().append($('#content'));cela exécutera une balise de script placée dans le hachage. C'est une bonne habitude à utiliser à la $('body').find('ul'+hash+':first')place $('ul'+hash+':first').
Tgr
40
Certains navigateurs renvoient le symbole de hachage, d'autres non, il est donc plus sûr de l'utiliser:var hash = location.hash.replace('#', '');
Tim
12
Alice gère un site Web, Bob le visite, s'authentifie et reçoit un cookie de session. (Un peu de temps peut s'écouler ici, Bob pourrait même fermer son navigateur.) Charlie envoie à Bob un e-mail lui disant "regarde ce lien sympa!". Bob ouvre le lien, qui mène à un site contrôlé par Charlie. La page redirige le navigateur de Bob vers une page du site d'Alice avec une charge d'attaque dans le hachage. La charge utile est exécutée, et comme le navigateur se souvient toujours des cookies, il peut simplement les envoyer à Charlie.
Tgr
2
@Tgr, merci d'avoir élaboré et connecté les points. Cet exemple concret me rend (et j'espère que d'autres) plus enclin à la vigilance pour assurer la sécurité des choses.
snapfractalpop
2
@buffer: $(userInput)est généralement dangereux car il $est surchargé et peut rechercher des nœuds existants ou en créer de nouveaux selon que la chaîne contient des <>caractères. $(document).find(userInput)recherchera toujours les nœuds existants afin qu'il soit moins dangereux. Cela dit, la meilleure pratique consiste à toujours nettoyer les entrées de l'utilisateur, par exemple, si vous utilisez des identifiants alphanumériques, assurez-vous qu'ils sont alphanumériques.
Tgr
35

location.hash n'est pas sûr pour IE , dans le cas d'IE (y compris IE9), si votre page contient iframe, puis après une actualisation manuelle à l'intérieur du contenu iframe, la valeur location.hash est ancienne (valeur pour le chargement de la première page). alors que la valeur récupérée manuellement est différente de location.hash, récupérez-la toujours via document.URL

var hash = document.URL.substr(document.URL.indexOf('#')+1) 
Deepak Patil
la source
7
Mise à jour: document.URL ne contient pas de valeur de hachage sur Firefox 3.6, donc location.href est sûr var hash = location.href.substr (location.href.indexOf ('#') + 1)
Deepak Patil
4

Pour ceux qui recherchent une solution javascript pure

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

J'espère que cela vous fera gagner du temps.

Matas Vaitkevicius
la source
3

Depuis jQuery 1.9, le :targetsélecteur correspondra au hachage de l'URL. Vous pouvez donc faire:

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

Ce qui sélectionnerait l'élément avec l'ID correspondant au hachage et l'afficherait.

j08691
la source
existe-t-il un moyen d'extraire le hachage sous forme de chaîne au lieu de l'identifiant de correspondance?
ina le
@ina Voulez-vous dire obtenir le hachage de jQuery :targetsous forme de chaîne? Si c'est le cas, je ne le crois pas.
j08691 le
1

Je suggérerais mieux cek d'abord si la page actuelle a un hachage. Sinon, ce sera le cas undefined.

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

J'utilise ceci pour aborder les implications de sécurité notées dans la réponse de @ 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...
    }
});
bonbon
la source