Междоменная IFrame element.scrollIntoView () Проблема с Safari - PullRequest
0 голосов
/ 09 февраля 2019

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

У меня есть веб-сайт, на котором я хотел бы предложить пользователям встраивать их в сайт с помощью (полной страницы) IFrame.Проблема только в некоторых версиях Safari.Элементы в IFrame не могут прокручивать себя в поле зрения.

enter image description here

Я замечаю, что если я провожу тот же тест домена, IFrame может прокручивать себя, используя window.parent.scrollTo(0,element.top).Это работает, но не кросс-домен.Еще одна странность заключается в том, что ни одному другому браузеру не нужен метод window.parent для прокрутки IFrame, только Safari.Все другие браузеры могут использовать element.scrollIntoView() из IFrame.Обратите внимание, что я уже использую обходной путь JavaScript , чтобы порадовать Safari кросс-протокольными IFrames.

Еще одна проблема, с которой я столкнулся только в Safari Mobile внутри IFrame, заключается в том, что Bootstrap Modals появляются вне поля зрения наверхняя часть IFrame при прокрутке вниз.Хотя я уверен, что если мы сможем правильно установить положение прокрутки, мы также сможем установить модальное положение.

Вот что я пробовал;

 1. window.frames['IFrameName'].document.
    getElementById("elmId").scrollIntoView();
Трюк смещения Velocity.js

Мое последнее средство здесь (я думаю) - это использовать postMessage из моего IFrame для уведомления родительского доменаустановить положение прокрутки кадра.

Мне кажется, что эта проблема существует очень долго.Есть ли лучший подход, чем этот?

1 Ответ

0 голосов
/ 10 февраля 2019

Это закончилось гораздо большим исследованием, чем код.То, что происходило, было - у меня был код, который изменял размер IFrame на основе содержимого.

Во всех других браузерах это работает нормально и убирает полосы прокрутки.Оказывается, Safari автоматически изменяет размеры Iframe , оставляя свои собственные свитки.В моем приложении нет нулевых статических страниц.Это оставляет меня с проблемой невозможности использовать исправление scrolling=no, описанное в ссылке.

После точного выяснения того, что происходит, я использовал другой подход к исправлению elm.scrollIntoView().Код - это больше комментариев, чем все, кроме важных частей:

  1. Определение, когда применять исправление Iframe с помощью RequiresIframeScrollFix
  2. Использование elm.getBoundingClientRect().top для получения нашей позиции прокрутки изнутриiframe.
  3. Общение с родителем для прокрутки с помощью window.parent.postMessage
  4. Получение сообщения от родителя с помощью window.addEventListener('message',...)

Вот как это выглядит.

Сайт Iframe

Наш сайт Iframe в настоящее время прокручивает свои элементы в виде, подобном этому elm.scrollIntoView(); Мы изменили это на следующее.

if (RequiresIframeScrollFix())
     window.parent.postMessage(elm.getBoundingClientRect().top, "*"); // Tell IFrame parent to do the scrolling. If this is not a test environment, replace "*" with the parent domain.
 else
     elm.scrollIntoView(); // If not scroll into view as usual.

Необязательно: исправлено модальное позиционирование начальной загрузки в IFrames IOS с использованием elm.getBoundingClientRect().top.

$('#modalId').css('top', elm.getBoundingClientRect().top); // This fixes modal not in view on Safari Iframes.

RequiresIframeScrollFix() в основном состоит из некоторого кода документа скважины, лежащего вокруг SO, чтобы определить, находимся ли мы в Iframeна IPad или IPhone.

// Used to help identify problematic userAgents.
var debugNavigator = false;

// Detects an issue on mobile where the Parent is an iframe which cannot have it's scroll bars removed.
// Presumably not a bug as safari will autosize it's iframes: https://salomvary.com/iframe-resize-ios-safari.html
// Can use "scrolling=no" fix instead if the parent knows the initial size of your iframe.
function RequiresIframeScrollFix() {
    try {
        // Debug navigator Agent
        if (debugNavigator)
            alert(navigator.userAgent);

        // We know this issue happens inside an IFrame on;
        // Safari iPhone
        // Safari iPad
        // Safari Desktop Works fine.

        // Check for safari
        var is_safari = navigator.userAgent.indexOf("Safari") > -1;
        // Chrome has Safari in the user agent so we need to filter (https://stackoverflow.com/a/7768006/1502448)
        var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
        if ((is_chrome) && (is_safari)) { is_safari = false; }

        // If we need to narrow this down even further we can use a more robust browser detection (https://stackoverflow.com/questions/5916900)
        // Problematic browsers can be adjusted here.
        if (is_safari && inIframe() && (
                navigator.userAgent.match(/iPad/i) ||
                navigator.userAgent.match(/iPhone/i)
                ))
            return true;
        else
            return false;

    } catch (e) {
        alert(e.message);
    }
}

// (/283115/kak-opredelit-zagruzhaetsya-li-veb-stranitsa-vnutri-iframe-ili-neposredstvenno-v-okne-brauzera)
function inIframe() {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

Родительский сайт

Наш родительский сайт содержит IFrame, размер которого автоматически определен Safari Mobile.Поэтому родительский сайт теперь имеет собственные полосы прокрутки, а не IFrame.Мы устанавливаем наш слушатель внутри родительского сайта, чтобы прокручивать себя, когда он получает сообщение от сайта IFramed.

// Safari Mobile Iframe Cross Domain Scroll Fix.
window.onload = function () {
     // Calback function to process our postMessages.
     function receiveMessage(e) {
          try {
               // Set the scroll position from our postMessage data.
               // Non-Test pages should uncomment the line below.
               //if (e.origin.includes("your-iframe-domain.com"))
               window.scrollTo(0, e.data);
           }
           catch (err) {
           }
      }

      // Setup and event to receives messages form our iframe (or window)
      window.addEventListener('message', receiveMessage);
}

Надеемся, что это поможет кому-то еще разобрать проблемы Safari Iframe на мобильном телефоне.Кроме того, дайте мне знать, если я пропустил лучшее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...