2016-07-24 11 views
7

Hat Google Chrome unter Windows Probleme beim Rendern von iframe-Bildlaufleisten?IFrame-Bildlaufleiste verschwindet in Chrome, wenn sich die Sichtbarkeit ändert

Ich schrieb einen sehr einfachen Code zu zeigen, was (bei mir zumindest auf Chrom 52.0.2743.82 m) passiert:

<button>Toggle visibility</button> 
    <br /> 
    <iframe scrolling="yes" seamless src="https://en.wikipedia.org/wiki/Lorem_ipsum" frameborder="0" style="width: 700px; height: 300px"></iframe> 

    <script type="text/javascript"> 
    $("button").on("click", function() { 
     $("iframe").toggle(); 
    }); 
    </script> 

Plunker link to code

Wenn die Seite geladen wird, der iframe, wie es Bildlaufleiste sind sichtbar.

Den iframe ausblenden und anzeigen, indem Sie auf die Schaltfläche klicken. Die Bildlaufleiste verschwindet.

Dieses Problem tritt anscheinend nur in Chrom auf.

Jeder erlebt das auch? Irgendwelche Korrekturen/Workarounds?

+0

Es scheint, dass Fehler mit Chrome erschienen 52.0.2743.82: http://googlechromereleases.blogspot.fr/2016/07/stable-channel-update.html – lepix

Antwort

4

Es scheint, dass Fehler erschien mit dem Update Chrome 52.0.2743.82 (http://googlechromereleases.blogspot.fr/2016/07/stable-channel-update.html)

Eine mögliche Abhilfe ist das Attribut visibility mit position: absolute stattdessen zu verwenden von display zum Anzeigen oder Verbergen der iframe.

Ein Chrom-Bug-Ticket gibt es für diesen Artikel: https://bugs.chromium.org/p/chromium/issues/detail?id=641881

+0

Frage zu diesem, das Anzeigeattribut ist entscheidend, und meine Website kann nicht ohne es funktionieren, irgendwelche Alternativen, um diesen Fehler zu umgehen? Und gibt es auch Informationen über eine mögliche Lösung von Google? Sind sie sich dessen bewusst? –

+0

Ich kann dieses Problem in Chrome 54 reproduzieren, aber ich kann keinen berichteten Fehler in https://bugs.chromium.org finden - existiert er oder soll ich einen neuen einreichen? – Dai

-2

hinzufügen

iframe { overflow-y: scroll; } 

zu Ihrem CSS

3

Ich habe dieses Problem hatte, und mit visibility statt display: none war keine Option.

Meine Problemumgehung war overflow: scroll auf der <body> des Dokuments, das im iframe angezeigt wird, wenn ich den iframe wieder sichtbar sein soll. Dies scheint zu erzwingen, dass die Bildlaufleiste erneut auf dem Iframe erscheint. Sie können dann die overflow auf ihren alten Wert zurücksetzen, und die Bildlaufleiste bleibt auf dem iFrame. Sie müssen für neu streichen warten, bevor Sie die overflow zurücksetzen können, obwohl, so dass ich dies mit Verzögerung in einem Timeout setzen 0.

function showIframe(iframe) { 
    var iframeBody = iframe.contentDocument.body; 
    $(iframe).show(); 
    var oldOverflow = iframeBody.css("overflow"); 
    iframeBody.css("overflow", "scroll"); 
    window.setTimeout(function() { 
     iframeBody.css("overflow", oldOverflow); 
    }, 0); 
} 

Es gibt eine „Flash“ von Scrollbar mit dieser Problemumgehung wenn der iframe in Frage Es muss jedoch nicht geblättert werden, daher kann es sinnvoll sein, die Problemumgehung visibility für den kurzen Moment zu verwenden, in dem das Repaint erforderlich ist, um den Flash zu vermeiden.

1

Hier ist ein Workaround, den ich für eine Anwendung entwickelt habe, die ich erstelle. Es hat mehrere Elemente in einem Foundation Tab-Steuerelement.

verwenden ich MutationObserver zu beobachten, wenn die 's übergeordnetes Element (ein Element Foundation div.tabs-content div.content) active wird, dann wechseln wir die iframe' s overflow Eigenschaft des Dokuments. Der Laufzeit-Effekt ist nicht nachvollziehbar.

ich ursprünglich observe die direkt wollte, jedoch wurden keine DOME Mutationsereignisse ausgelöst, wenn der Iframe selbst display Eigenschaft verändert hat, ich denke, technisch, weil element.style Werte sprechen ist nicht Teil der DOM-Struktur richtig.

Hier ist mein Code (Vanilla.js, keine jQuery). Wenn Sie in Ihrer Anwendung verwenden möchten Sie meinen Sicht-Erkennungscode mit etwas ersetzen, die zu Ihrem Dokument anwendbar ist:

window.addEventListener('DOMContentLoaded', function(e) { 

    var observer = new MutationObserver(onContentMutated); 
    var options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['class'] }; 

    var iframeContainers = document.querySelectorAll('.tabs-content .content'); 
    for(var i = 0; i < iframeContainers.length; i++) { 

     observer.observe(iframeContainers[i], options); 
    } 
}); 

function onContentMutated(mutations) { 

    for(var i = 0; i < mutations.length; i++) { 
     var m = mutations[i]; 

     var thisIsNowAnActiveTab = m.target.classList.contains('active'); 
     if(thisIsNowAnActiveTab) { 
      // get the corresponding iframe and fiddle with its DOM 

      var iframes = m.target.getElementsByTagName("iframe"); 
      if(iframes.length == 0) continue; 
      var iframe = iframes[0]; 

      iframe.contentWindow.document.documentElement.style.overflow = 'hidden'; 

      // the timeout is to trigger Chrome to recompute the necessity of the scrollbars, which makes them visible again. Because the timeout period is 0 there should be no visible change to users. 
      setTimeout(function(s) { 

       s.overflow = 'auto'; 

      }, 0, iframe.contentWindow.document.documentElement.style); 
     } 

     console.log(m.type); 
    } 
} 
1

Für das gegebene Beispiel können Sie tun:
$("iframe").toggle(1)

In meinem Fall funktionierte es durch die Höheneinstellung zurück:
$("iframe").css("height", "100%")

0

ich auf Chrome mit einem iframe ein ähnliches Problem hatte eine jQuery UI Registerkarte eingebettet in. Wenn die Registerkarte mit dem Iframe zum ersten Mal angezeigt wird, wird die Bildlaufleiste angezeigt. Aber wenn ich zu einem anderen Tab und zurück zum Tab mit dem Iframe wechsle, verschwindet die Bildlaufleiste. Alle hier vorgeschlagenen Lösungen funktionierten nicht für mich. Hier ist, was ich das Problem zu beheben tat: Zunächst erstelle ich die Tabs:

$("#mytabs").tabs(); 

Dann habe ich eine Funktion für das Ereignis „tabsactivate“ binden und ich überprüfen, ob das Ziel auf das Register ein mit dem Iframe . Wenn es der Fall, dass ich eine Funktion fixChromeScrollBar() aufrufen später beschrieben:

$("#mytabs").on("tabsactivate", function(event, ui) { 
    if ($(event.originalEvent.target).attr("href") == "#mytab-with-iframe") { 
     fixChromeScrollBar(); 
    } 
}); 

Und schließlich ist hier die Funktion fixChromeScrollBar(), die den Überlauf-Stil-Attribut des iframe Körper setzt (wie schon gesagt) entweder auf " scrollen "oder" auto ". Mir ist aufgefallen, dass wenn ich nur den "auto" oder "scroll" Wert definiere, wenn ich zu einem anderen Tab und zurück zum iframe wechsle, die Scrollbalken verliere. Die einzige Möglichkeit, sie beizubehalten, besteht darin, bei jedem Erscheinen des Iframes zwischen den beiden Werten zu wechseln. Es ist seltsam, aber es funktioniert:

function fixChromeScrollBar() { 
    var iFrameBody = $("#myiframe").contents().find("body"); 
    var originalOverflow = $(iFrameBody).css("overflow"); 
    if (originalOverflow == "visible" || originalOverflow == "auto") { 
     $(iFrameBody).css("overflow", "scroll"); 
    } else { 
     $(iFrameBody).css("overflow", "auto"); 
    } 
} 

Sie feststellen können, dass diese Methode nur aufgerufen, wenn Sie auf die Registerkarte wechseln die iframe enthält, so dass, wenn Sie mehrere Male auf dieser Registerkarte klicken, ohne diesen Code auf eine andere Schalt wird nur beim ersten Mal ausgeführt werden.

0

Anscheinend Einstellung src frischt iframe in Chrom, für gegebenen Beispiel-Code wird:

<script type="text/javascript"> 
    $("button").on("click", function() { 
     $('iframe').toggle().attr('src', function(i, val) { return val; }); 
    }); 
</script> 
+0

Möchten Sie erklären, warum es funktioniert, anstatt nur Code zu schreiben? –

0

ich Dais Beispiel meiner eigenen Reaktion IFrame-Komponente angepasst. Ich habe einen iframe innerhalb eines Tab-Panels, das sich selbst in einem reduzierbaren Panel befindet. Wenn einer der beiden aktiviert wird, erzwinge ich, dass der Iframe neu gezeichnet wird. Es funktioniert wunderbar.

private iframe: HTMLIFrameElement; 
private displayObserver: MutationObserver; 

componentDidMount() { 
    // Detect style attribute changes for the containing collapsible components 
    // If the display goes from 'none' to something else, then we need to redraw the iframe 
    // so we get the scrollbar back as it should be. 
    if (isChrome()) { 
     this.displayObserver = new MutationObserver(this.onContentMutated); 
     const options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['style'] }; 

     const tabPanelAncestor = this.findAncestor(this.iframe, '.tab-panel-content'); 
     if (tabPanelAncestor) { 
      this.displayObserver.observe(tabPanelAncestor, options); 
     } 
     const collapsibleAncestor = this.findAncestor(this.iframe, '.collapsible'); 
     if (collapsibleAncestor) { 
      this.displayObserver.observe(collapsibleAncestor, options); 
     } 
    } 
} 

private readonly onContentMutated = (mutations: Array<MutationRecord>) => { 

    R.forEach((mutation) => { 
     const targetElement = mutation.target as Element; 
     const style = targetElement.getAttribute('style'); 
     if (style && !style.match(/display: none/)) { 
      this.iframe.contentWindow.location.reload(true); 
     } 
    }, mutations); 
} 

private readonly findAncestor = (element: HTMLElement, sel: string): Node | null => { 
    if (typeof element.closest === 'function') { 
     return element.closest(sel) || null; 
    } 
    let ancestor: HTMLElement | null = element; 
    while (ancestor) { 
     if (ancestor.matches(sel)) { 
      return ancestor; 
     } 
     ancestor = ancestor.parentElement; 
    } 
    return null; 
} 
Verwandte Themen