IFRAMEs и Safari на iPad, как пользователь может прокручивать содержимое?


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

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

12 69

12 ответов:

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

-webkit-overflow-scrolling:touch

-webkit-overflow-scrolling:touch Как уже упоминалось в ответе, это infact возможное решение.

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

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

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

enter image description here

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

не похоже, что iframes отображаются и прокручиваются правильно. Вы можете использовать тег объекта для замены 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>

Это не мой ответ, но я просто скопировал его из 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>

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

работает при применении как к рассматриваемому iframe, так и к его родительскому 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 Отмечать 1) не тестируется на других системах ios 2) не проверял это на Android браузерах на планшетах, могут потребоваться дополнительные изменения

(Так что это решение может быть не полным)

приведенный ниже код работает для меня (спасибо Кристоферу Циммерману за его сообщение в блогеhttp://dev.magnolia-cms.com/blog/2012/05/strategies-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>
    

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

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

главная.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>

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

<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>

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

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

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.

Проблема

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

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

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

Решение

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

вот такой рабочий скрипка* и вот код:

(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, '||').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, '||').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.

после Большого обострения я обнаружил, как прокручивать iframes на моем ipad. Секрет заключался в том, чтобы сделать вертикальный палец (один палец был в порядке) на левой стороне области iframe (и, возможно, немного за пределами границы). На ноутбуке или ПК полоса прокрутки находится справа, поэтому, естественно, я провел много времени на своем ipad, экспериментируя с движениями пальцев с правой стороны. Только когда я попробовал левую сторону прокрутки фрейма.

добавить overflow: auto; к стилю и два пальца прокрутки должны работать.