IFRAMEs et Safari sur iPad, comment l’utilisateur peut-il faire défiler le contenu?

Selon le mantra Apple iOS, il devrait être possible de faire défiler le contenu d’un IFRAME en le faisant glisser avec deux doigts. Malheureusement, sous la dernière version d’iOS sur l’iPad, je n’ai pas encore trouvé un seul site Web avec un IFRAME qui défile en utilisant cette méthode – aucune barre de défilement ne s’affiche non plus.

Est-ce que quelqu’un sait comment un utilisateur est censé faire défiler le contenu d’un IFRAME avec le Safari mobile?

iOS 5 a ajouté le style suivant qui peut être ajouté au div parent afin que le défilement fonctionne.

-webkit-overflow-scrolling:touch

-webkit-overflow-scrolling:touch comme mentionné dans la réponse est la solution possible.

 

Mais si vous ne parvenez pas à faire défiler vers le haut ou vers le bas à l’intérieur de l’iframe, comme illustré ci-dessous, entrer la description de l'image ici

vous pouvez essayer de faire défiler avec 2 doigts en diagonale comme ceci,

entrer la description de l'image ici

Cela a fonctionné dans mon cas, donc il suffit de le partager si vous n’avez pas encore trouvé de solution.

Il ne semble pas que les iframes s’affichent et défilent correctement. Vous pouvez utiliser une balise d’object pour remplacer un iframe et le contenu sera défilable avec 2 doigts. Voici un exemple simple:

      
HEADER - use 2 fingers to scroll contents:
FOOTER

Ce n’est pas ma réponse, mais je viens de la copier depuis https://gist.github.com/anonymous/2388015 simplement parce que la réponse est géniale et corrige complètement le problème. Le crédit va complètement à l’auteur anonyme.

   

Comme mentionné dans d’autres articles, la combinaison des valeurs CSS de débordement: auto; & -webkit-overflow-scrolling: touchez;

fonctionne lorsqu’il est appliqué à la fois l’iframe en question et son div parent

Avec les effets secondaires malheureux des doubles barres de défilement sur les navigateurs non tactiles.

La solution que j’ai utilisée consistait à append ces valeurs css via javascript / jquery. Ce qui m’a permis d’utiliser un css de base pour tous les navigateurs

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

où isSafariBrowser () est défini comme suit …

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

Cela a permis à mon application de fonctionner sur un iPad Note 1) Non testé sur d’autres systèmes ios 2) Non testé sur les navigateurs Android sur les tablettes, peut nécessiter des modifications supplémentaires

(donc cette solution peut ne pas être complète)

Le code ci-dessous fonctionne pour moi (merci à Christopher Zimmermann pour son blog http://dev.magnolia-cms.com/blog/2012/05/strategies-for-the-iframe-on-the-ipad-problem/ ) . Les problèmes sont les suivants:

  1. Aucune barre de défilement ne permet à l’utilisateur de savoir qu’il peut faire défiler
  2. Les utilisateurs doivent utiliser le défilement à deux doigts
  3. Les fichiers PDF ne sont pas centrés (fonctionnent encore dessus)

     < !DOCTYPE HTML>   Testing iFrames on iPad  

     
    Here are some additional contents.

C’est ce que j’ai fait pour que le défilement de l’iframe fonctionne sur iPad. Notez que cette solution ne fonctionne que si vous contrôlez le code HTML affiché dans l’iframe.

En fait, il désactive le défilement iframe par défaut et fait défiler la balise body à l’intérieur de l’iframe.

main.html :

 < !DOCTYPE html>      

test.html :

 < !DOCTYPE html>    

La même chose pourrait probablement être accomplie en utilisant jQuery si vous préférez:

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

J’ai utilisé cette solution pour que TinyMCE (wordpress editor) défile correctement sur l’iPad.

Basé sur cet article , j’ai mis en place l’extrait suivant qui fournit des fonctionnalités très basiques:

 

Evidemment, c’est loin d’être parfait (étant donné que cela augmente pratiquement la hauteur de votre page à l’infini), mais c’est la seule solution viable que j’ai trouvée jusqu’à présent.

Aucune des solutions n’a jusqu’à présent fonctionné pour moi lorsque j’ai essayé (parfois, seulement des bugs sur des charges secondaires), mais comme solution de contournement, en utilisant un élément d’object tel que décrit ici, puis en enveloppant un div défilant, haute hauteur (5000px) a fait le travail pour moi. C’est une grande solution de contournement et ne fonctionne pas incroyablement bien (pour les débutants, les pages de plus de 5000px causeraient des problèmes – 10000px le cassaient complètement pour moi), mais cela semble fonctionner dans certains cas de test:

 var style = 'left: ...px; top: ...px; ' + 'width: ...px; height: ...px; border: ...'; if (isIOs) { style += '; overflow: scroll !important; -webkit-overflow-scrolling: touch !important;'; html = '
' + '' + '
'; } else { style += '; overflow: auto;'; html = ''; }

En espérant qu’Apple répare les problèmes de Safari iFrame.

Le problème

J’aide à maintenir un vieux site complexe, compliqué et désordonné dans lequel tout (littéralement) est nested dans plusieurs niveaux d’iframes, dont beaucoup sont créés dynamicment et / ou ont un src dynamic. Cela crée les défis suivants:

  1. Toute modification de la structure HTML risque de briser les scripts et les feuilles de style qui n’ont pas été touchés depuis des années.
  2. Trouver et réparer manuellement tous les iframes et les documents src prendrait beaucoup trop de temps et d’efforts.

Parmi les solutions affichées jusqu’à présent, c’est la seule que j’ai vue qui surmonte le défi 1. Malheureusement, cela ne semble pas fonctionner sur certains iframes, et quand c’est le cas, le défilement est très glitch (ce qui semble causer d’autres problèmes). bogues sur la page, tels que les liens sans réponse et les contrôles de formulaire).

La solution

Si ce qui précède ressemble à votre situation, vous pouvez essayer le script suivant. Il renonce au défilement natif et rend tous les iframes déplaçables dans les limites de leur fenêtre d’affichage. Il vous suffit de l’append au document contenant les iframes de niveau supérieur; elle appliquera le correctif au besoin à eux et à leurs descendants.

Voici un violon de travail *, et voici le code:

 (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 , masortingxPrefix, masortingxSuffix , masortingxRegex = /(.*([\.\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(masortingxRegex, '$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 }; } })(); } })(); 

* Le support de la souris jsfiddle est activé à des fins de test. Sur un site de production, vous souhaitez définir mouse = false.

Après beaucoup d’aggravation, j’ai découvert comment faire défiler les iframes sur mon ipad. Le secret était de faire un coup de doigt vertical (un seul doigt se portait bien) du côté GAUCHE de la zone iframe (et peut-être légèrement en dehors de la frontière). Sur un ordinateur portable ou un PC, la barre de défilement est à droite, alors naturellement, j’ai passé beaucoup de temps sur mon ipad à tester les mouvements des doigts du côté droit. Ce n’est que lorsque j’essaierai le côté gauche que le défilement de l’iframe se fera.

Ajouter un overflow: auto; au style et le défilement des deux doigts devrait fonctionner.