Как я могу обновить window.location.hash без перескакивания документа?
У меня есть скользящая панель, настроенная на моем сайте.
Когда он закончил анимацию, я задал хэш так:
function() {
window.location.hash = id;
}
(это обратный вызов, а id
назначается ранее).
Это хорошо работает, чтобы пользователь мог добавлять закладки в панель, а также для версии, не поддерживающей JavaScript.
Однако, когда я обновляю хэш, браузер переходит к местоположению. Я предполагаю, что это ожидаемое поведение.
Мой вопрос: как я могу это предотвратить? То есть как я могу изменить хеш окна, но не, чтобы браузер просматривал элемент, если хеш существует? Какой-то тип event.preventDefault()
?
Я использую jQuery 1.4 и scrollTo plugin.
Большое спасибо!
Update
Вот код, который изменяет панель.
$('#something a').click(function(event) {
event.preventDefault();
var link = $(this);
var id = link[0].hash;
$('#slider').scrollTo(id, 800, {
onAfter: function() {
link.parents('li').siblings().removeClass('active');
link.parent().addClass('active');
window.location.hash = id;
}
});
});
Ответы
Ответ 1
Существует обходной путь с использованием API истории в современных браузерах с резервным копированием старых:
if(history.pushState) {
history.pushState(null, null, '#myhash');
}
else {
location.hash = '#myhash';
}
Кредит отправляется Lea Verou
Ответ 2
Проблема заключается в том, что вы устанавливаете window.location.hash атрибут идентификатора элемента. Это ожидаемое поведение браузера для перехода к этому элементу, независимо от того, является ли вы "preventDefault()" или нет.
Один из способов обойти это - префикс хэша с произвольным значением:
window.location.hash = 'panel-' + id.replace('#', '');
Затем все, что вам нужно сделать, это проверить префикс хеш на загрузку страницы. В качестве дополнительного бонуса вы можете даже сгладить ее прокрутку, так как теперь вы контролируете значение хэша...
$(function(){
var h = window.location.hash.replace('panel-', '');
if (h) {
$('#slider').scrollTo(h, 800);
}
});
Если вам нужно, чтобы это работало постоянно (а не только на начальной загрузке страницы), вы можете использовать функцию для контроля изменений хеш-значения и перехода на правильный элемент "на лету":
var foundHash;
setInterval(function() {
var h = window.location.hash.replace('panel-', '');
if (h && h !== foundHash) {
$('#slider').scrollTo(h, 800);
foundHash = h;
}
}, 100);
Ответ 3
Дешевое и неприятное решение. Используйте уродливые #! стиль.
Чтобы установить его:
window.location.hash = '#!' + id;
Чтобы прочитать это:
id = window.location.hash.replace(/^#!/, '');
Так как он не соответствует, а привязка или идентификатор на странице, он не будет прыгать.
Ответ 4
Почему бы вам не получить текущую позицию прокрутки, поместить ее в переменную, а затем назначить хеш и поместить прокрутку страницы туда, где она была:
var yScroll=document.body.scrollTop;
window.location.hash = id;
document.body.scrollTop=yScroll;
это должно работать
Ответ 5
Я использовал комбинацию решения Attila Fulop (Lea Verou) для современных браузеров и решения Gavin Brock для старых браузеров следующим образом:
if (history.pushState) {
// IE10, Firefox, Chrome, etc.
window.history.pushState(null, null, '#' + id);
} else {
// IE9, IE8, etc
window.location.hash = '#!' + id;
}
Как заметил Гэвин Брок, чтобы захватить идентификатор, вам придется обрабатывать строку (которая в этом случае может иметь или не быть "!" ) следующим образом:
id = window.location.hash.replace(/^#!?/, '');
До этого я попробовал решение, аналогичное тому, которое было предложено пользователем706270, но оно не очень хорошо работает с Internet Explorer: поскольку его механизм Javascript не очень быстрый, вы можете заметить увеличение и уменьшение прокрутки, что приводит к неприятным визуальный эффект.
Ответ 6
Я не уверен, что вы можете изменить исходный элемент, но как переключиться с использования id attr на что-то еще, например, на идентификатор данных? Затем просто прочитайте значение id-данных для вашего хеш-значения, и оно не будет прыгать.
Ответ 7
Это решение сработало для меня.
Проблема с настройкой location.hash
заключается в том, что страница перейдет к этому идентификатору, если он найден на странице.
Проблема с window.history.pushState
заключается в том, что он добавляет запись в историю для каждой вкладки, которую нажимает пользователь. Затем, когда пользователь нажимает кнопку " back
, он переходит на предыдущую вкладку. (это может или не может быть то, что вы хотите. это было не то, что я хотел).
Для меня более replaceState
является replaceState
, replaceState
он заменяет только текущую историю, поэтому, когда пользователь нажимает кнопку " back
, он переходит на предыдущую страницу.
$('#tab-selector').tabs({
activate: function(e, ui) {
window.history.replaceState(null, null, ui.newPanel.selector);
}
});
Ознакомьтесь с документацией по истории API на MDN.
Ответ 8
При использовании laravel Framework у меня были некоторые проблемы с использованием функции route-> back(), так как она стерла мой хэш. Чтобы сохранить мой хэш, я создал простую функцию:
$(function() {
if (localStorage.getItem("hash") ){
location.hash = localStorage.getItem("hash");
}
});
и я установил это в моей другой функции JS следующим образом:
localStorage.setItem("hash", myvalue);
Вы можете назвать ваши значения локального хранилища так, как вам нравится; мой по имени hash
.
Поэтому, если хэш установлен на PAGE1, а затем вы переходите к PAGE2; хеш будет воссоздан на PAGE1, когда вы нажмете Back на PAGE2.
Ответ 9
Это решение сработало для меня
// store the currently selected tab in the hash value
if(history.pushState) {
window.history.pushState(null, null, '#' + id);
}
else {
window.location.hash = id;
}
// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
$('#myTab a[href="' + hash + '"]').tab('show');
И мой полный код JS
$('#myTab a').click(function(e) {
e.preventDefault();
$(this).tab('show');
});
// store the currently selected tab in the hash value
$("ul.nav-tabs > li > a").on("shown.bs.tab", function(e) {
var id = $(e.target).attr("href").substr(1);
if(history.pushState) {
window.history.pushState(null, null, '#' + id);
}
else {
window.location.hash = id;
}
// window.location.hash = '#!' + id;
});
// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
// console.log(hash);
$('#myTab a[href="' + hash + '"]').tab('show');
Ответ 10
[H] Как я могу изменить хеш окна, но браузер не прокручивает до элемента, если хеш существует?
Чтобы изменить хеш и не использовать прокрутку браузера, используйте scrollRestorationMode
. У него есть два значения:
"auto"
- пользовательский агент отвечает за восстановление позиции прокрутки при навигации. (дефолт)
"manual"
- страница отвечает за восстановление позиции прокрутки.
Установите значение "manual"
в вашем скрипте перед обновлением истории:
history.scrollRestoration = 'manual';
document.history.pushState({}, null, '#slider');
Я использую jQuery 1.4 и плагин scrollTo.
Попробуйте использовать scroll-behavior
вместо значения smooth
для более плавного хода.