2011-01-04 27 views
69

Secondo il mantra di Apple iOS dovrebbe essere possibile scorrere il contenuto di un IFRAME trascinandolo con due dita. Sfortunatamente, con l'ultima versione di iOS sull'iPad, non ho ancora trovato un singolo sito web con un IFRAME che scorre usando questo metodo - non compare nemmeno la barra di scorrimento.IFRAME e Safari su iPad, come può l'utente scorrere il contenuto?

Qualcuno sa come si suppone che un utente debba scorrere il contenuto di un IFRAME con Safari mobile?

+1

Non ho avuto problemi con l'utilizzo di 2 dita. Non vengono visualizzate barre di scorrimento, ma il contenuto scorre. – ughoavgfhw

+0

Trasforma la domanda in superutente e pubblica un sito di esempio che non funziona. Lo scorrimento a due dita funziona su tutti i siti che ho provato con il mio iPad. –

+1

Certamente non funziona con l'ultima versione di iOS (4.2.1) prova l'esempio del sito w3: http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_iframe Confronta come la pagina guarda l'iPad e un browser desktop. Completamente diverso e senza scorrimento possibile. Questa è una domanda di programmazione in quanto è una questione di quali bit di stile devono essere impostati sull'IFRAME o su un DIV circostante perché lo scorrimento funzioni. – Karlth

risposta

83

iOS 5 ha aggiunto il seguente stile che può essere aggiunto al div genitore in modo che lo scorrimento funzioni.

-webkit-overflow-scrolling:touch

+13

Ho scoperto che devo aggiungere questo come uno stile sul genitore div. Se lo imposto usando 'jQuery (" # div "). Css (" - webkit-overflow-scrolling "," touch ")' allora non funziona. Inoltre, ora devi combinarlo con 'overflow: auto' che significa che * potresti * ottenere doppie barre di scorrimento su alcuni browser non touch ... – frumbert

+7

Il seguente jQuery sugar funziona per me: https://gist.github.com/2388015 (questo è molto semplice e non implementa la copia dei bordi) –

+0

Funziona con ChromeApp su iPad? Funziona su Safari Mobile –

8

Non sembra che gli iframe vengano visualizzati e scorrano correttamente. È possibile utilizzare un tag oggetto per sostituire un iframe e il contenuto sarà scorrevole con 2 dita. Ecco un semplice esempio:

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

Purtroppo anche questo non funziona. Sembra che l'iframe a due dita e lo scorrimento degli oggetti si siano interrotti in 4.2.1 (sebbene funzioni per le caselle di testo). Speriamo che Apple risolverà questo fastidioso bug nella prossima versione. – Karlth

+0

Qualcuno come una fonte valida su questo bug? Ti piace da Apple? – twDuke

-1

Dopo tanto aggravamento, ho scoperto come scorrere gli iframe sul mio ipad. Il segreto era quello di fare uno scorrimento verticale del dito (un dito andava bene) sul lato SINISTRA dell'area iframe (e forse leggermente al di fuori del confine). Su un laptop o PC, la barra di scorrimento è sulla destra, quindi, naturalmente, ho trascorso molto tempo sul mio ipad sperimentando con movimenti delle dita sul lato destro. Solo quando ho provato il lato sinistro sarebbe il rotolo di iframe.

+2

Non funziona. Almeno non in tutti i casi. – Karlth

-1

Aggiungere overflow: auto; allo stile e il rotolo due dita dovrebbe funzionare.

+1

Non sfortunatamente. La risposta corretta è indicata sopra. – Karlth

+0

devi utilizzare entrambi per indirizzare gli iPad più vecchi o più recenti o le persone non più aggiornate su iOS – frumbert

2

Questo è quello che ho fatto per far scorrere gli iframe su iPad. Nota che questa soluzione funziona solo se controlli l'html che viene visualizzato all'interno dell'iframe.

In realtà, lo scorrimento iframe predefinito viene disattivato e fa scorrere il tag body all'interno dell'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> 

Lo stesso probabilmente potrebbe essere realizzato utilizzando jQuery, se si preferisce:

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

I usato questa soluzione per ottenere TinyMCE (editor di wordpress) per scorrere correttamente sull'iPad.

+0

La jQuery dovrebbe contenere virgole anziché punti e virgola. Altrimenti questo sembra buono. Grazie! – Fmstrat

2

Il codice seguente funziona per me (grazie a Christopher Zimmermann per il suo post sul blog http://dev.magnolia-cms.com/blog/2012/05/strategies-for-the-iframe-on-the-ipad-problem/).I problemi sono:

  1. Non ci sono barre di scorrimento per permettere all'utente di sapere che essi possono scorrere
  2. Gli utenti devono utilizzare due dita scrolling
  3. I file PDF non sono centrate (ancora lavorando su di esso)

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

5

Come accennato in altri post, la combinazione dei valori CSS di overflow: auto; & -webkit-overflow-scrolling: touch;

opere quando applicata sia l'iframe in questione e il suo div genitore

Con l'infelice effetto collaterale di doppie barre di scorrimento sui browser non-touch.

La soluzione che ho usato è stata quella di aggiungere questi valori CSS tramite javascript/jquery. Che mi ha permesso di usare un css di base per tutti i browser

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

dove isSafariBrowser() è definita come 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; 
} 

Questo ha permesso la mia applicazione per lavorare su un iPad Nota 1) Non testato su altri sistemi ios 2) Non testato su browser Android su tablet, potrebbe richiedere ulteriori modifiche

(quindi questa soluzione potrebbe non essere completa)

+2

'function isSafariBrowser() {return is_safari &&! Is_chrome; } 'Oltre al fatto che non hai bisogno di una funzione per questo. – Pavlo

+0

hai giocato a golf! – JohnStone

21

-webkit-overflow-scrolling:touch come indicato nella risposta è infatti la possibile soluzione.

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

Ma se non si riesce a scorrere verso l'alto e verso il basso all'interno del iframe, come mostrato nell'immagine qui sotto, enter image description here

si potrebbe provare a scorrimento con 2 dita in diagonale come questo,

enter image description here

Questo ha funzionato nel mio caso, quindi basta condividerlo se non hai ancora trovato una soluzione per questo.

+0

Questo ha funzionato per me! – skwidbreth

0

Sulla base di this article, ho messo insieme il seguente frammento che fornisce alcune funzionalità di base:

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

Ovviamente è lontano dall'essere perfetto (dato che si espande in pratica la vostra altezza della pagina a infinito), ma è l'unica soluzione percorribile che ho trovato finora.

0

Nessuna delle soluzioni finora ha funzionato completamente per me quando ho provato (a volte, solo con errori sui carichi secondari), ma come soluzione alternativa, utilizzando un elemento oggetto come descritto qui, quindi il wrapping in un div scorrevole, quindi l'impostazione del oggetto ad un'altezza molto alta (5000px) ha fatto il lavoro per me. È una grande soluzione e non funziona molto bene (per i principianti, le pagine superiori a 5000px causerebbero problemi - 10000px mi ha completamente distrutto) ma sembra che il lavoro venga svolto in alcuni dei miei casi di test:

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>'; 
} 

Ecco sperando che Apple risolva i problemi di Safari iFrame.

7

Questa non è la mia risposta, ma l'ho appena copiata da https://gist.github.com/anonymous/2388015 solo perché la risposta è eccezionale e risolve il problema completamente. Il merito va completamente all'autore anonimo.

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

Il problema

ho aiutare a mantenere un grande, complicato, disordinato vecchio sito in cui tutto (letteralmente) è nidificato in molteplici livelli di iframes-- molte delle quali sono create in modo dinamico e/o avere un src dinamico. Ciò crea le seguenti sfide:

  1. Qualsiasi modifica alla struttura HTML rischia di scomporre script e fogli di stile che non sono stati toccati in anni.
  2. Trovare e correggere manualmente tutti i documenti iframe e src richiederebbe troppo tempo e fatica.

delle soluzioni pubblicate finora, this è l'unico che ho visto che vince sfida 1. Purtroppo, non sembra di lavorare su alcuni iframe, e quando lo fa, lo scorrimento è molto glitchy (che sembra causare altri bug nella pagina, come link non rispondenti e controlli del modulo).

La soluzione

Se quanto sopra suona qualcosa di simile la vostra situazione, si consiglia di dare il seguente script una prova. Rinuncia allo scrolling nativo e rende invece tutti gli iframe trascinabili all'interno dei limiti del proprio viewport. Devi solo aggiungerlo al documento che contiene gli iframe di primo livello; applicherà la correzione secondo necessità a loro e ai loro discendenti.

Ecco un lavoro fiddle *, ed ecco il codice:

(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 
     }; 
     } 
    })(); 
    } 
})(); 

* Il jsfiddle ha abilitato il supporto del mouse a scopo di test. Su un sito di produzione, dovresti impostare mouse = false.