Моя основная цель
Приложение Rails, которое может загружать новый контент через Ajax, используя HTML5 для поддержания истории истории браузера.У меня супер базовая версия приложения , работающая на Heroku.Я также настроил общедоступный репозиторий GitHub , чтобы весь код, упомянутый ниже, можно было рассмотреть более подробно.
Проблема
Я успешно реализовал базовыйприложение, использующее API истории браузера HTML5 (в какой-то момент я также сделал версию, используя плагин History.js jQuery).Все работает как надо, пока пользователь не нажмет на ссылку, не являющуюся Ajax, а затем нажмет кнопку «Назад».Например, если пользователь щелкнул элемент 2, приложение успешно загрузит новый контент и изменит состояние браузера.Если они нажимают кнопку «Назад», он также корректно перезагружает предыдущее содержимое и изменяет состояние браузера обратно, чтобы соответствовать.Но если пользователь затем просматривает другую веб-страницу (любую другую страницу в Интернете), а затем нажимает кнопку «Назад» своего браузера, приложение Rails отображает необработанный javascript вместо исходной страницы.
Все работает до последнего шага,когда контроллер начинает возвращать необработанный javascript из show.js.erb вместо show.html.erb.Я попытался изменить несколько настроек в контроллере, но я не могу понять, что конкретно вызывает это.Я точно знаю, что если я удалю вызов history.pushState из show.js.erb, проблема прекратится (хотя, очевидно, я теряю всю функциональность истории браузера, которую я искал в первую очередь).
Любые идеи?
Бонус: мучительная деталь
Вот как все это работает (я думаю!).
Пользователь нажимает на ссылку, которая выглядит под капотом:
<%= link_to number_to_human(volume.number), volume_path(volume), :remote => true %>
Это отправляет запрос javascript на контроллер, который выглядит следующим образом:
def show
@volume = Volume.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.js # show.js.erb
format.json { render json: @volume }
end
end
Это передает запрос в show.js.erb, который выглядит следующим образом:
var stateObject = {"html": "<%= escape_javascript render(@volume) %>"};
history.pushState(stateObject,'',"<%= escape_javascript volume_path(@volume) %>");
$('#volumes').fadeTo(0, 0);
$('#volumes').html(stateObject.html).fadeTo('slow', 1.0);
, который затем заменяет содержимое тега div на исходной странице и использует pushState для создания объекта состояния и измененияURL страницы.
Затем пользователь может нажать кнопку «Назад» и JavaScript, прикрепленный к событию window.onpopstate в show.html.erb, перезагрузит соответствующий контент:
if(history.pushState) {
window.onpopstate = function(event) {
if (event.state != null) {
$('#volumes').html(event.state.html);
}
}
}