IFRAMEs и Safari на iPad, как пользователь может прокрутить контент? - PullRequest
70 голосов
/ 05 января 2011

Согласно мантре Apple iOS, должна быть возможность прокручивать содержимое IFRAME, перетаскивая его двумя пальцами. К сожалению, при запуске последней версии iOS на iPad, я еще не нашел ни одного веб-сайта с IFRAME, который прокручивает этот метод - полосы прокрутки тоже не появляются.

Кто-нибудь знает, как пользователь должен прокручивать содержимое IFRAME с помощью мобильного Safari?

Ответы [ 12 ]

87 голосов
/ 21 ноября 2011

В iOS 5 добавлен следующий стиль, который можно добавить в родительский div, чтобы прокрутка работала.

-webkit-overflow-scrolling:touch

24 голосов
/ 26 августа 2013

-webkit-overflow-scrolling:touch, как указано в ответе, является возможным решением.

<div style="overflow:scroll !important; -webkit-overflow-scrolling:touch !important;">
     <iframe src="YOUR_PAGE_URL" width="600" height="400"></iframe>
</div>

Но если вы не можете прокручивать вверх и вниз внутри фрейма, как показано на рисунке ниже, enter image description here

Вы можете попробовать прокрутить двумя пальцами по диагонали, как это,

enter image description here

Это действительно работает в моем случае, поэтому просто поделитесь им, если вы до сих пор не нашли решение для этого.

9 голосов
/ 06 января 2011

Похоже, что фреймы отображаются и прокручиваются правильно.Вы можете использовать тег объекта, чтобы заменить iframe, и содержимое будет прокручиваться двумя пальцами.Вот простой пример:

<html>
    <head>
        <meta name="viewport" content="minimum-scale=1.0; maximum-scale=1.0; user-scalable=false; initial-scale=1.0;"/>
    </head>
    <body>
        <div>HEADER - use 2 fingers to scroll contents:</div>
        <div id="scrollee" style="height:75%;" >
            <object id="object" height="90%" width="100%" type="text/html" data="http://en.wikipedia.org/"></object>
        </div>
        <div>FOOTER</div>
    </body>
</html>
7 голосов
/ 07 ноября 2014

Это не мой ответ, но я просто скопировал его из https://gist.github.com/anonymous/2388015 только потому, что ответ потрясающий и полностью решает проблему. Кредит полностью переходит к анониму.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        if (/iPhone|iPod|iPad/.test(navigator.userAgent))
            $('iframe').wrap(function(){
                var $this = $(this);
                return $('<div />').css({
                    width: $this.attr('width'),
                    height: $this.attr('height'),
                    overflow: 'auto',
                    '-webkit-overflow-scrolling': 'touch'
                });
            });
    })
</script>
5 голосов
/ 27 февраля 2013

Как уже упоминалось в других сообщениях, комбинация css-значений переполнения: auto;& -webkit-overflow-scrolling: touch;

работает применительно к ОБА рассматриваемому фрейму и его родительскому div

С неблагоприятным побочным эффектом двойной полосы прокрутки в не сенсорных браузерах.

Решением, которое я использовал, было добавление этих значений CSS через javascript / jquery.Это позволило мне использовать базовый CSS для всех браузеров

if (isSafariBrowser()){
    $('#parentDivID').css('overflow', 'auto');
    $('#parentDivID').css('-webkit-overflow-scrolling', 'touch');
    $('#iframeID').css('overflow', 'auto');
    $('#iframeID').css('-webkit-overflow-scrolling', 'touch');
}

, где isSafariBrowser () определяется как foll ...

var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
var is_safari = navigator.userAgent.indexOf("Safari") > -1;

function isSafariBrowser(){
    if (is_safari){
        if (is_chrome)  // Chrome seems to have both Chrome and Safari userAgents
            return false;
        else
            return true;
    }
    return false;
}

Это позволило моему приложению работать на iPad Note1) Не тестировался в других системах ios. 2) Не тестировался в браузерах Android на планшетах. Возможно, потребуются дополнительные изменения

(поэтому данное решение может быть неполным)

2 голосов
/ 01 августа 2012

Приведенный ниже код работает для меня (спасибо Кристоферу Циммерману за его сообщение в блоге http://dev.magnolia -cms.com / blog / 2012/05 / Strategic for the-iframe-on-the-ipad-problem/ ).Проблемы:

  1. Нет полос прокрутки, чтобы пользователь знал, что он может прокручивать
  2. Пользователи должны использовать прокрутку двумя пальцами
  3. Файлы PDF не центрированы (все еще работают над ним)

    <!DOCTYPE HTML>
    <html>
    <head>
      <title>Testing iFrames on iPad</title>
      <style>
      div {
        border: solid 1px green;
        height:100px;
      }
    
    .scroller{
        border:solid 1px #66AA66;
        height: 400px;
        width: 400px;
        overflow: auto;
        text-align:center;
    
    }
    </style>
    

    <table>
      <tr>
        <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
        <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
      </tr>
      <tr>
      <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
        <td><div class="scroller">
        <iframe width="400" height="400" src="http://www.supremecourt.gov/opinions/11pdf/11-393c3a2.pdf" ></iframe>
    </div>
        </td>
      </tr>
    </table>
    <div> Here are some additional contents.</div>
    

2 голосов
/ 19 июня 2012

Это то, что я сделал, чтобы прокрутка iframe работала на iPad. Обратите внимание, что это решение работает только в том случае, если вы управляете HTML, который отображается внутри iframe.

Это фактически отключает прокрутку iframe по умолчанию и вместо этого вызывает прокрутку тега body внутри iframe.

main.html

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#container {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 400px;
    height: 300px;
    overflow: hidden;
}
#iframe {
    width: 400px;
    height: 300px;
}
</style>
</head>
<body>

    <div id="container">
        <iframe src="test.html" id="iframe" scrolling="no"></iframe>
    </div>

</body>
</html>

test.html :

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html { 
    overflow: auto; 
    -webkit-overflow-scrolling: touch; 
}
body {
    height: 100%;
    overflow: auto; 
    -webkit-overflow-scrolling: touch;
    margin: 0;
    padding: 8px;
}
</style>
</head>
<body>
…
</body>
</html>

То же самое можно сделать с помощью jQuery, если вы предпочитаете:

$("#iframe").contents().find("body").css({
    "height": "100%",
    "overflow": "auto", 
    "-webkit-overflow-scrolling": "touch"
});

Я использовал это решение, чтобы заставить TinyMCE (редактор WordPress) правильно прокручивать на iPad.

0 голосов
/ 04 февраля 2016

Проблема

Я помогаю поддерживать большой, сложный, грязный старый сайт, в котором все (буквально) вложено в несколько уровней фреймов, многие из которых создаются динамически и / или имеют динамический источник. Это создает следующие проблемы:

  1. Любые изменения в структуре HTML могут привести к нарушению работы скриптов и таблиц стилей, которые не затрагивались годами.
  2. Поиск и исправление всех iframes и src-документов вручную займет слишком много времени и усилий.

Из решений, опубликованных до сих пор, этот - единственный, который я видел, который преодолевает проблему 1. К сожалению, он не работает на некоторых фреймах, а когда это происходит, прокрутка очень глючно (что может вызвать другие ошибки на странице, такие как не отвечающие ссылки и элементы управления формой).

Решение

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

Вот рабочая скрипка *, а вот код:

(function() {
  var mouse = false //Set mouse=true to enable mouse support
    , iOS = /iPad|iPhone|iPod/.test(navigator.platform);
  if(mouse || iOS) {
    (function() {
      var currentFrame
        , startEvent, moveEvent, endEvent
        , screenY, translateY, minY, maxY
        , matrixPrefix, matrixSuffix
        , matrixRegex = /(.*([\.\d-]+, ?){5,13})([\.\d-]+)(.*)/
        , min = Math.min, max = Math.max
        , topWin = window;
      if(!iOS) {
        startEvent = 'mousedown';
        moveEvent = 'mousemove';
        endEvent = 'mouseup';
      }
      else {
        startEvent = 'touchstart';
        moveEvent = 'touchmove';
        endEvent = 'touchend';
      }
      setInterval(scrollFix, 500);
      function scrollFix() {fixSubframes(topWin.frames);}
      function fixSubframes(wins) {for(var i = wins.length; i; addListeners(wins[--i]));}
      function addListeners(win) {
        try {
          var doc = win.document;
          if(!doc.draggableframe) {
            win.addEventListener('unload', resetFrame);
            doc.draggableframe = true;
            doc.addEventListener(startEvent, touchStart);
            doc.addEventListener(moveEvent, touchMove);
            doc.addEventListener(endEvent, touchEnd);
          }
          fixSubframes(win.frames);
        }
        catch(e) {}
      }
      function resetFrame(e) {
        var doc = e.target
          , win = doc.defaultView
          , iframe = win.frameElement
          , style = getComputedStyle(iframe).transform;
        if(iframe===currentFrame) currentFrame = null;
        win.removeEventListener('unload', resetFrame);
        doc.removeEventListener(startEvent, touchStart);
        doc.removeEventListener(moveEvent, touchMove);
        doc.removeEventListener(endEvent, touchEnd);
        if(style !== 'none') {
          style = style.replace(matrixRegex, '$1|$3|$4').split('|');
          iframe.style.transform = style[0] + 0 + style[2];
        }
        else iframe.style.transform = null;
        iframe.style.WebkitClipPath = null;
        iframe.style.clipPath = null;
        delete doc.draggableiframe;
      }
      function touchStart(e) {
        var iframe, style, offset, coords
          , touch = e.touches ? e.touches[0] : e
          , elem = touch.target
          , tag = elem.tagName;
        currentFrame = null;
        if(tag==='TEXTAREA' || tag==='SELECT' || tag==='HTML') return;
        for(;elem.parentElement; elem = elem.parentElement) {
          if(elem.scrollHeight > elem.clientHeight) {
            style = getComputedStyle(elem).overflowY;
            if(style==='auto' || style==='scroll') return;
          }
        }
        elem = elem.ownerDocument.body;
        iframe = elem.ownerDocument.defaultView.frameElement;
        coords = getComputedViewportY(elem.clientHeight < iframe.clientHeight ? elem : iframe);
        if(coords.elemTop >= coords.top && coords.elemBottom <= coords.bottom) return;
        style = getComputedStyle(iframe).transform;
        if(style !== 'none') {
          style = style.replace(matrixRegex, '$1|$3|$4').split('|');
          matrixPrefix = style[0];
          matrixSuffix = style[2];
          offset = parseFloat(style[1]);
        }
        else {
          matrixPrefix = 'matrix(1, 0, 0, 1, 0, ';
          matrixSuffix = ')';
          offset = 0;
        }
        translateY = offset;
        minY = min(0, offset - (coords.elemBottom - coords.bottom));
        maxY = max(0, offset + (coords.top - coords.elemTop));
        screenY = touch.screenY;
        currentFrame = iframe;
      }
      function touchMove(e) {
        var touch, style;
        if(currentFrame) {
          touch = e.touches ? e.touches[0] : e;
          style = min(maxY, max(minY, translateY + (touch.screenY - screenY)));
          if(style===translateY) return;
          e.preventDefault();
          currentFrame.contentWindow.getSelection().removeAllRanges();
          translateY = style;
          currentFrame.style.transform = matrixPrefix + style + matrixSuffix;
          style = 'inset(' + (-style) + 'px 0px ' + style + 'px 0px)';
          currentFrame.style.WebkitClipPath = style;
          currentFrame.style.clipPath = style;
          screenY = touch.screenY;
        }
      }
      function touchEnd() {currentFrame = null;}
      function getComputedViewportY(elem) {
        var style, offset
          , doc = elem.ownerDocument
          , bod = doc.body
          , elemTop = elem.getBoundingClientRect().top + elem.clientTop
          , elemBottom = elem.clientHeight
          , viewportTop = elemTop
          , viewportBottom = elemBottom + elemTop
          , position = getComputedStyle(elem).position;
        try {
          while(true) {
            if(elem === bod || position === 'fixed') {
              if(doc.defaultView.frameElement) {
                elem = doc.defaultView.frameElement;
                position = getComputedStyle(elem).position;
                offset = elem.getBoundingClientRect().top + elem.clientTop;
                viewportTop += offset;
                viewportBottom = min(viewportBottom + offset, elem.clientHeight + offset);
                elemTop += offset;
                doc = elem.ownerDocument;
                bod = doc.body;
                continue;
              }
              else break;
            }
            else {
              if(position === 'absolute') {
                elem = elem.offsetParent;
                style = getComputedStyle(elem);
                position = style.position;
                if(position === 'static') continue;
              }
              else {
                elem = elem.parentElement;
                style = getComputedStyle(elem);
                position = style.position;
              }
              if(style.overflowY !== 'visible') {
                offset = elem.getBoundingClientRect().top + elem.clientTop;
                viewportTop = max(viewportTop, offset);
                viewportBottom = min(viewportBottom, elem.clientHeight + offset);
              }
            }
          }
        }
        catch(e) {}
        return {
          top: max(viewportTop, 0)
          ,bottom: min(viewportBottom, doc.defaultView.innerHeight)
          ,elemTop: elemTop
          ,elemBottom: elemBottom + elemTop
        };
      }
    })();
  }
})();

* В jsfiddle включена поддержка мыши для тестирования. На производственном сайте вы хотите установить mouse = false.

0 голосов
/ 23 октября 2014

Ни одно из решений до сих пор полностью не работало для меня, когда я пытался (иногда, только глючит при вторичных нагрузках), но в качестве обходного пути, используя элемент объекта, как описано здесь, затем оборачивая прокручиваемый div, затем устанавливая объект на очень высокий рост (5000 пикселей) сделал работу для меня. Это большой обходной путь, и он не работает невероятно хорошо (для начала, страницы размером более 5000 пикселей вызовут проблемы - хотя 10000 пикселей полностью меня сломали), но, похоже, в некоторых моих тестовых примерах это сделано:

var style = 'left: ...px; top: ...px; ' +
        'width: ...px; height: ...px; border: ...';

if (isIOs) {
    style += '; overflow: scroll !important; -webkit-overflow-scrolling: touch !important;';
    html = '<div style="' + style + '">' +
           '<object type="text/html" data="http://example.com" ' +
           'style="width: 100%; height: 5000px;"></object>' +
           '</div>';
}
else {
    style += '; overflow: auto;';
    html = '<iframe src="http://example.com" ' +
           'style="' + style + '"></iframe>';
}

Надеемся, что Apple исправит проблемы Safari iFrame.

0 голосов
/ 20 октября 2014

Основываясь на этой статье , я собрал следующий фрагмент кода, который предоставляет некоторые базовые функции:

<div id = "container"></div>
<script>
function setPDFHeight(){ 
        $("#pdfObject")[0].height = $("#pdfObject")[0].offsetHeight;   
}   
$('#container').append('<div align="center" style="width: 100%; height:100%; overflow: auto !important; -webkit-overflow-scrolling: touch !important;">\
      <object id="pdfObject" width="100%" height="1000000000000" align="center" data="content/lessons/12/t.pdf" type="application/pdf" onload="setPDFHeight()">You have no plugin installed</object></div>');  
</script>

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

...