Почему в Safari не запускается popstate при загрузке iframe? - PullRequest
4 голосов
/ 18 мая 2011

В Safari, если есть загрузка iframe, и пользователь изменяет состояние истории, перемещаясь назад или вперед, событие popstate не вызывается, из-за чего состояние приложения и расположение окна не синхронизируются .

Я думаю, что активный XHR-запрос будет вызывать то же поведение, но я пока не смог это подтвердить.

Вот jsfiddle, который позволит вам легко воспроизвести проблему: http://jsfiddle.net/neonsilk/muHk8/

Вам нужно просто нажимать ссылки / кнопки по порядку, от 1 до 6.

В Safari 5.0.5 вывод:

(обратный хронологический, важная часть - сравнение состояния вверху)

[1305665493096] /
[1305665493096] vs
[1305665493096] /node
---------------
[1305665489955] iframe loaded
---------------
[1305665489806] (did popstate or $.address change trigger?)
[1305665489805] called history.back()
[1305665489805] appended iframe
---------------
[1305665488428] popstate: /node
[1305665488427] $.address change: /node
---------------
[1305665487821] popstate: /
[1305665487821] $.address change: /
---------------
[1305665487179] $.address change: /node
---------------
[1305665486606] $.address change: /
---------------
[1305665485732] iframe loaded
---------------
[1305665485569] $.address change: /neonsilk/muHk8/show/
[1305665485568] $.address init

Тем не менее, в Chrome (11) или FireFox (4.0) вывод выглядит следующим образом:

(обратите внимание, что состояния синхронизированы)

[1305665609499] /
[1305665609499] vs
[1305665609499] /
---------------
[1305665608360] iframe loaded
---------------
[1305665607770] popstate: /
[1305665607770] $.address change: /
[1305665607758] (did popstate or $.address change trigger?)
[1305665607758] called history.back()
[1305665607758] appended iframe
---------------
[1305665606870] popstate: /node
[1305665606869] $.address change: /node
---------------
[1305665606150] popstate: /
[1305665606149] $.address change: /
---------------
[1305665605551] $.address change: /node
---------------
[1305665604808] $.address change: /
---------------
[1305665603354] iframe loaded
---------------
[1305665602688] $.address change: /neonsilk/muHk8/show/
[1305665602682] $.address init
[1305665602676] popstate: /neonsilk/muHk8/show/

Это ошибка в Safari? И если это так, кто-нибудь обнаружил обходной путь?

(Интересно также, что FireFox и Chrome запускают событие popstate при загрузке страницы.)

Ответы [ 2 ]

1 голос
/ 10 октября 2013
  1. Загрузка IMG / script / iframe сломает popstate, но XHR НЕ подвержен этой ошибке!
  2. назад / вперед до того, как загрузка документа будет отложена. Мы получим одно popstate при загрузке. (всплывет только последнее состояние, даже если есть несколько вперед / назад.)

(протестировано под Android 2.2 и Safari на iOS 4.3.3)

Итак, обходной путь:

Используйте XHR вместо img для отслеживания / предварительной загрузки независимо от события загрузки.

Мы по-прежнему можем столкнуться с проблемой, если пользователь делает два раза вперед или назад перед событием загрузки, но пользователь редко будет выполнять несколько действий, если время загрузки короткое, и потому что конечное состояние правильное, поэтому я думаю, что это нормально. *

И еще один обходной путь:

Наблюдая за URL с помощью таймера, если он был изменен без popstate, сделайте грязную работу самостоятельно. (Как комментарии к этой ошибке, Facebook использовал это решение.)

Но этот метод слишком сложен, потому что вы должны сериализовать / десериализовать состояние в url или localalstorage / sessionstorage, точно так же, как у вас нет History API. Поэтому я не думаю, что это приемлемый обходной путь.

1 голос
/ 18 мая 2011

Обновление

Насколько я могу судить, об этой ошибке впервые сообщил Бен Черри .

Вот соответствующий отчет об ошибке и changeset из WebKit.

И вопрос из хрома .

Мне не удалось выяснить, когда ошибка была исправлена ​​в Chrome. Если кто-то еще, я был бы очень признателен за информацию.

Я знаю, что ошибка существует в WebKit 533.21.1 (который используется в Safari 5.0.5) и была исправлена ​​в 534.36 (Safari / WebKit nightly) - но я не знаю, и пока нет Я не смог выяснить, какая промежуточная сборка представила исправление.

Существует полезная диаграмма , которая отображает версию Chrome на версию WebKit.

Наиболее важно , эта ошибка возникает, когда любой активный сетевой трафик (загрузка изображений, запросы Ajax и т. Д.), А не только iframes. Если вы пытаетесь реализовать поддержку History API или используете последнюю версию плагина jQuery Address Asual (по умолчанию включена поддержка истории), эта ошибка может серьезно повлиять на ваше приложение.


2-е обновление

Кажется, я нашел точную версию WebKit, в которой было исправлено (534.10). Итак, если вы используете плагин jQuery и адрес Asual, вот практическое решение:

if (!($.browser.webkit === true && parseFloat($.browser.version) < 534.10)) {
    // only enable state support if WebKit version >= 534.10
    $.address.state("/base/path");
}

Надеюсь, это кому-нибудь поможет!


Я только что протестировал скрипку в последней версии WebKit (r86671), и состояние остается синхронизированным, поэтому это должно быть ошибкой. Забавно, что тратить много времени на написание вопроса и его отправку сразу же вдохновляет ответ.

Тем не менее, если у кого-то есть обходной путь, он будет очень признателен.

WebKit nightly (r86671):

[1305666598481] /
[1305666598481] vs
[1305666598480] /
---------------
[1305666597469] iframe loaded
---------------
[1305666597300] popstate: /
[1305666597298] $.address change: /
[1305666597270] (did popstate or $.address change trigger?)
[1305666597269] called history.back()
[1305666597269] appended iframe
---------------
[1305666596605] popstate: /node
[1305666596605] $.address change: /node
---------------
[1305666596008] popstate: /
[1305666596008] $.address change: /
---------------
[1305666595555] $.address change: /node
---------------
[1305666595142] $.address change: /
---------------
[1305666578600] iframe loaded
---------------
[1305666578400] $.address change: /_display/
[1305666578400] $.address init
---------------
[1305666577964] popstate: /_display/

Также интересно, что Safari теперь соответствует поведению Chrome и FireFox, запуская popstate при загрузке страницы.

...