История HTML 5 - window.pushState не работает

Я пытаюсь ajax загрузить содержимое центра и обновить URL-адрес, не меняя страницу. Все это работает нормально, за исключением тех пор, пока я не попытаюсь получить доступ к истории. Кажется, что window.pushState неправильно записывает мой URL-адрес или событие popstate не работает должным образом. Я могу успешно загрузить предыдущую страницу с помощью ajax, но если я нажимаю назад более одного раза, она остается на той же странице. Любая помощь будет принята с благодарностью!

$(document).ready(function() {
    $('area, .ajax_link').live('click', function(event) {
        change_image(this, event);
    });

    window.addEventListener('popstate', function(event) {
        change_image(window.location, event);
    });
});

function change_image(e, event) {
    if($(e).attr('target') != '_blank') {
        event.preventDefault();
        $.post(
            base_url+'/kit/ajax_load',
            { url: this_url},
            function(return_data) {
                $('#content img').attr('src', return_data.image_src);
                $('map').html(return_data.imagemap);
            },
            'json'
        );
        history.pushState(null, null, this_url);
        update_links(this_url);
      }
}

person Steve    schedule 12.09.2011    source источник
comment
Есть ли конкретный браузер, в котором вы видите это поведение, или оно одинаково во всех браузерах, которые вы пробовали, которые поддерживают pushState?   -  person daxelrod    schedule 13.09.2011
comment
Протестировано в Chrome и Firefox, такое же поведение.   -  person Steve    schedule 13.09.2011


Ответы (3)


Проблема решена

@Oliver Nightingale: мне нужно было удалить history.pushState из моей функции change_image. Вы не можете вызывать history.pushState во время onpopstate. Вот весь рабочий код. Я сократил его выше только для того, чтобы включить необходимые части, о которых идет речь. Далее я добавлю несколько запасных вариантов. Это проверено и работает в Chrome и Firefox. Проверено и не работает в IE.

$(document).ready(function() {
  $('area, .ajax_link').live('click', function(event) {
      history.pushState(null, null, $(this).attr('href'));
      change_image(this, event);
  });

  window.addEventListener('popstate', function(event) {
      change_image(window.location, event);
  });
});

function change_image(e, event) {
    if(!e instanceof jQuery) {
    var this_url = e;
    }
    else {
        var this_url = $(e).attr('href');
    }

    if($(e).attr('target') != '_blank') {
    event.preventDefault();
        $.post(
            base_url+'/kit/ajax_load',
            { url: this_url},
            function(return_data) {
                $('#content img').attr('src', return_data.image_src);
                $('map').html(return_data.imagemap);
            },
            'json'
        );

        update_links(this_url);
    }
}
person Steve    schedule 13.09.2011
comment
Спасибо. У меня была та же проблема (история не работала, потому что я непреднамеренно вызывал pushState внутри popState). Теперь вы можете принять свой собственный ответ, чтобы сделать его более заметным на странице. - person TRiG; 07.05.2014

Основная часть функции change_image происходит в popstate? Если это так, похоже, что вы отправляете новое состояние каждый раз, когда извлекаете состояние, это может вызывать некоторые проблемы.

Если вы используете pushState для маршрутизации, вы можете попробовать использовать библиотеку, например Davis, чтобы упростить задачу.

person Oliver Nightingale    schedule 13.09.2011
comment
Да, основная часть функции change_image всегда происходит в popstate. Я не видел Дэвиса, но я видел History.js и плагин истории Jquery HTML5. Похоже, что использование библиотеки для этого может быть ответом, но независимо от библиотеки мне все равно нужно pushState внутри моей функции onpopstate, верно? Как еще этот URL будет добавлен в историю? - person Steve; 13.09.2011
comment
ой, я не позволю мне вставить это сюда, пожалуйста, смотрите мой ответ ниже. - person Steve; 13.09.2011

Как $(e).attr('target') != '_blank', когда e это window.location?

Поскольку вы используете нативный HTML5 History API, вам также понадобится проверка перед history.pushState(null, null, this_url);, чтобы вызывать ее только в том случае, если мы пришли по ссылке.

Плюс window.addEventListener('popstate', function(event) { переменная event здесь на самом деле является данными состояния.

См. следующие сведения для рабочих примеров:

person balupton    schedule 13.09.2011