В моем проекте Django у меня есть страница с таблицей устройств и формой для добавления нового устройства. А теперь я хочу перевести этот пост в AJAX. Я сделал это с помощью jQuery Form Plugin (http://malsup.github.com/jquery.form.js):
$('#deviceAddForm').ajaxForm({
dataType: 'json',
async: true,
cache: false,
success: function (data) {
device_row = '<tr>' +
'<td>' + data['name'] + '</td>' +
'<td>' + data['description'] + '</td>' +
'</tr>';
$(device_row).hide().appendTo($('#deviceTableBody')).show("slow")
}
});
И теперь у меня проблема с браузером "кнопка назад". Если пользователь публикует некоторые устройства, переходит на другой сайт, а затемНазад (с помощью кнопки «Назад» в браузере) дополнительное содержимое AJAX не отображается.
Эта проблема является обычной для AJAX, и все найденные решения относятся к History API . Содержимое AJAX обновляется, должен быть history.pushState
вызов, а кнопки браузера назад / вперед должны обрабатываться через событие window.onpopstate
. Может быть, я что-то упускаю, но этот способ работает, только если пользователь перемещается только на одной конкретной страницеСайт приложения (SPA). Если пользователь, например, заходит в Google и обратно, onpopstate
событие не сработает ( HTML5 History API: «popstate» не вызывается при переходе назад с другой страницы ). Похоже, что это не работает в каждом случае со SPA, и мой сайт даже не является SPA.
Я вижу простое решение - каждый раз перезагружать страницу даже для путешествий по истории. rsal:
function detectIE() {
// this function is needed cause IE reloads page
// even if it is accessed through browser back button
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older
return true;
}
var trident = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11
var rv = ua.indexOf('rv:');
return true;
}
return false;
}
if (!!window.performance && (window.performance.navigation.type == 2) && !detectIE()) {
window.location.reload()
}
(это работает, но, возможно, проверку кнопки «Назад» следует сочетать с новым PerformanceNavigationTiming API )
Но этот метод неэффективен, если перезагрузить страницузанимает много времени. Поэтому единственное решение, которое я придумал, это:
$('#deviceAddForm').ajaxForm({
dataType: 'json',
async: true,
cache: false,
success: function (data) {
device_row = '<tr>' +
'<td>' + data['name'] + '</td>' +
'<td>' + data['description'] + '</td>' +
'</tr>';
// save rows to sessionStorage
device_rows = (sessionStorage.getItem("device_rows") === null) ?
'' : sessionStorage.getItem("device_rows");
device_rows = device_rows + device_row;
sessionStorage.setItem("device_rows", device_rows);
$(device_row).hide().appendTo($('#deviceTableBody')).show("slow")
}
});
function detectIE() {
// this function is needed cause IE reloads page
// even if it is accessed through browser back button
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return true;
}
var trident = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
var rv = ua.indexOf('rv:');
return true;
}
return false;
}
if (!!window.performance && (window.performance.navigation.type == 2) && !detectIE()) {
// detect browser history travel
device_rows = sessionStorage.getItem("device_rows");
if (device_rows)
$(device_rows).hide().appendTo($('#deviceTableBody')).show("slow")
} else {
// page was refreshed
sessionStorage.removeItem("device_rows");
}
Все это кажется очень громоздким. Это правильный способ справиться с этими вещами? Публикация формы с помощью AJAX - это стандартная задача, но я не могу найти стандартное решение, чтобы сделать это правильно.