Отримання URL-адреси хеша URL-адреси та використання його в jQuery


135

Я хотів би отримати значення після хешу в URL-адресі поточної сторінки, а потім зможу застосувати це в новій функції ... наприклад.

URL-адреса могла бути

www.example.com/index.html#foo

І я хотів би використати це разом із наступним фрагментом коду

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

Я якось припускаю / сподіваюся, що існує якийсь спосіб схопити це і перетворити його в змінну, яку я потім можу використовувати у другому фрагменті коду.


8
Я не маю для вас жодного коду, але ви повинні переконатися, що санітирувати дані, оскільки це здається дозрілим для введення коду.
Нейт Б

Розуміння того, що це питання майже десятиліття, 'ul#foo:first'не має сенсу, оскільки ідентифікатори повинні бути унікальними, тому додавання :firstдо селектора є зайвим, якщо ви не дублюєте ідентифікатори, які є недійсними. Зауважте, що ще десятиліття тому повторні посвідчення особи все ще були недійсними.
j08691

Ще десять років тому помилявся
Дуглас

Відповіді:


280

Примітка редактора: підхід, наведений нижче, має серйозні наслідки для безпеки і, залежно від версії jQuery, яку ви використовуєте, може піддавати ваших користувачів атакам XSS. Більш детально дивіться обговорення можливої ​​атаки в коментарях до цієї відповіді або в цьому поясненні на Exchange Stack Exchange .

Ви можете використовувати location.hashвластивість, щоб схопити хеш поточної сторінки:

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

Зауважте, що ця властивість вже містить #символ на початку.

Насправді вам не потрібен :firstпсевдоселектор, оскільки ви використовуєте селектор ідентифікаторів , передбачається, що ідентифікатори є унікальними у DOM.

Якщо ви хочете отримати хеш із рядка URL-адреси, ви можете скористатися String.substringметодом:

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

Порада: Будьте в курсі, що користувач може змінювати хеш так, як він хоче, вводячи що-небудь у ваш селектор, ви повинні перевірити хеш перед його використанням.


30
Зауважте, що селектори jQuery можуть використовуватися для виконання спеціального коду JavaScript, тому використання несанітованих хешів - жахливо, жахливо небезпечно. Для цього в останніх версіях jQuery для селекторів є напівдодане виправлення, яке містить # перед введеним кодом, але ви все ще під загрозою, якщо видалити позначку # з початку location.hash. E. g. var hash = location.hash.slice(1); $('ul.item'+hash).show().append($('#content'));це виконає тег сценарію, покладений у хеш. Це корисна звичка використовувати $('body').find('ul'+hash+':first')замість цього $('ul'+hash+':first').
Тгр

40
Деякі броулери повертають хеш-символ, а деякі ні, тому безпечніше використовувати:var hash = location.hash.replace('#', '');
Тим,

12
Аліса запускає веб-сайт, Боб відвідує його, підтверджує автентифікацію та отримує сесійне cookie. (Тут може пройти якийсь час, Боб може навіть закрити свій браузер.) Чарлі надсилає Бобі повідомлення, "кажучи про це класне посилання!". Боб відкриває посилання, яке веде до сайту, керованого Чарлі. Сторінка переспрямовує браузер Боба на сторінку на сайті Аліси з атакою корисного навантаження в хеші. Корисне навантаження виконується, і оскільки браузер все ще запам'ятовує файли cookie, він може просто надіслати їх Чарлі.
Тгр

2
@Tgr, дякую за розробку та підключення крапок. Цей конкретний приклад змушує мене (і, сподіваюсь, інших) більше схильний до пильності в безпеці речей.
snapfractalpop

2
@buffer: $(userInput)зазвичай небезпечний, оскільки $перевантажений і може шукати наявні вузли або створювати нові, залежно від того, чи містить рядок <>символи. $(document).find(userInput)завжди буде шукати наявні вузли, тому він менш небезпечний. З огляду на це, найкраща практика - це завжди оновлювати введення даних користувачів, наприклад, якщо ви використовуєте буквено-цифрові ідентифікатори, переконайтеся, що вони буквено-цифрові.
Тгр

35

location.hash не є безпечним для IE , якщо IE (включаючи IE9), якщо на вашій сторінці міститься iframe, то після ручного оновлення вмісту iframe отримайте значення location.hash старе (значення для завантаження першої сторінки). а отримане вручну значення відрізняється від location.hash, тому завжди отримуйте його через document.URL

var hash = document.URL.substr(document.URL.indexOf('#')+1) 

7
Оновлення: document.URL не містить хеш-значення на firefox 3.6, тому location.href є безпечним var hash = location.href.substr (location.href.indexOf ('#') + 1)
Deepak Patil

4

Для тих, хто шукає чисте рішення JavaScript

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

Сподіваюсь, це заощадить певний час.


3

Оскільки jQuery 1.9, :targetселектор буде відповідати хешу URL-адреси. Так ви могли зробити:

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

Який би обрав елемент із ідентифікатором, що відповідає хешу, і показав би його.


чи є спосіб витягнути хеш як рядок замість ідентифікатора відповідності?
іна

@ina Ви маєте на увазі отримати хеш від jQuery's :targetяк рядок? Якщо так, я не вірю в це.
j08691

1

Я б запропонував краще cek спочатку, якщо на поточній сторінці є хеш. Інакше буде undefined.

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

1

Я використовую це для вирішення наслідків безпеки, зазначених у відповіді @ 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...
    }
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.