Как я могу обновить window.location.hash, не перепрыгивая документ? - PullRequest
146 голосов
/ 06 октября 2010

На моем сайте установлена ​​скользящая панель.

Когда он закончил анимацию, я установил хэш примерно так

function() {
   window.location.hash = id;
}

(это обратный вызов, и id назначается ранее).

Это хорошо работает, позволяя пользователю создавать закладки на панели, а также для работы с версией без JavaScript.

Однако, когда я обновляю хеш, браузер переходит к местоположению. Я предполагаю, что это ожидаемое поведение.

Мой вопрос: как я могу предотвратить это? То есть как я могу изменить хеш окна, но не прокручивает браузер до элемента, если хеш существует? Что-то вроде event.preventDefault()?

Я использую jQuery 1.4 и плагин scrollTo .

Большое спасибо!

Обновление

Вот код, который меняет панель.

$('#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;

            }
    });
});

Ответы [ 9 ]

230 голосов
/ 04 февраля 2013

Существует обходной путь с использованием API истории в современных браузерах с резервированием на старых:

if(history.pushState) {
    history.pushState(null, null, '#myhash');
}
else {
    location.hash = '#myhash';
}

Кредит переходит на Lea Verou

49 голосов
/ 24 марта 2011

Проблема в том, что вы устанавливаете window.location.hash для атрибута ID элемента.Ожидается, что браузер будет переходить к этому элементу независимо от того, используете ли вы «warnDefault ()» или нет.

Один из способов обойти это - поставить хеш с произвольным значением, например, так:

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);
26 голосов
/ 14 июня 2013

Дешевое и мерзкое решение .. Используй уродливый #!style.

Чтобы установить его:

window.location.hash = '#!' + id;

Чтобы прочитать его:

id = window.location.hash.replace(/^#!/, '');

Так как он не соответствует и привязывает или идентифицирует на странице, он выигралне прыгай.

13 голосов
/ 13 апреля 2011

Почему вы не получаете текущую позицию прокрутки, поместите ее в переменную, затем назначьте хэш и верните прокрутку страницы туда, где она была:

var yScroll=document.body.scrollTop;
window.location.hash = id;
document.body.scrollTop=yScroll;

это должно работать

10 голосов
/ 14 октября 2015

Я использовал комбинацию решения 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 не очень быстрый, вы можете заметить увеличение и уменьшение прокрутки, что приводит к неприятным последствиям. визуальный эффект.

1 голос
/ 01 ноября 2013

Я не уверен, что вы можете изменить исходный элемент, но как насчет переключения с использования идентификатора attr на что-то другое, например data-id?Затем просто прочитайте значение data-id для вашего хеш-значения, и оно не будет прыгать.

0 голосов
/ 14 ноября 2018

Это решение сработало для меня

// 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');
0 голосов
/ 29 августа 2018

При использовании 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.

0 голосов
/ 28 апреля 2018

Это решение сработало для меня.

Проблема с настройкой location.hash заключается в том, что страница перейдет к этому идентификатору, если он найден на странице.

Проблема с window.history.pushState заключается в том, что она добавляет запись в историюдля каждой вкладки пользователь нажимает.Затем, когда пользователь нажимает кнопку back, он переходит на предыдущую вкладку.(это может или не может быть то, что вы хотите. это было не то, что я хотел).

Для меня replaceState был лучшим вариантом в том, что он заменяет только текущую историю, поэтому, когда пользователь нажимает наКнопка back, они переходят на предыдущую страницу.

$('#tab-selector').tabs({
  activate: function(e, ui) {
    window.history.replaceState(null, null, ui.newPanel.selector);
  }
});

Ознакомьтесь с документами History API в MDN.

...