Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iFrame content disappears after using other tabs in same browser

There are many posts about disappearing iFrame content, but the ones I can find are about immediately disappearing, or randomly disappearing content.

My situation is a little different.

I have an iframe within a parent div:

<div id="punt" contentid="123">
    <iframe id="content_frame" sandbox="allow-forms allow-popups allow-scripts allow-same-origin" src="" ></iframe>
</div>

Where the iframe completely fills its parent, which itself is nearly the full-size of the viewport.

The content of the iframe is set via JS/JQuery:

function loadURL(url){
    $('#content_frame').attr('src', url);
}

Additionally, eventListeners are bound to the iframe

$("#content_frame").on("load", function () {
    if(isNewURL){
        bindAndFocus();
    }
});

where

function bindAndFocus(){
    $('#content_frame').bind({
        mouseenter: function(e) {
            overiFrame = $(this).parent().attr('contentid');
        },
        mouseleave: function(e) {
            overiFrame = -1;
        }
    });
}

When the content is cleared, the listener is dismissed:

$('#content_frame').unbind('mouseenter mouseleave');

And this all works great. The URL loads fine, the content is scrollable and can be interacted with as if viewing directly in the browser. The listener is a hacked-together attempt (from another SO post) at determining when the iframe has been interacted with - a little hit and miss, but not the issue at hand.

But then...

The Mysterious Disappearing Act!?

The issue comes when you load a URL into the iframe, and then play around in other tabs for a while (within the same browser). The disappearing is not instant - quickly switching between a few tabs and then back has no effect. But when you spend an amount of time in a different tab (few minutes, or longer), and then return, the content is partially disappeared.

To clarify...

If the content is long enough to scroll within the iframe (i.e. most web-pages), then only the portion that is visible disappears. Scrolling will show the rest of the loaded page, but the disappeared portion does not re-appear without reloading the content.

Visual to help clear-up any confusion:

iframe mess

In the image, the iframe is the red box. Anything inside is viewable, anything outside is hidden.

From left-to-right:

Before using other tabs

  1. URL loaded inside iframe

  2. Loaded page scrolls properly within iframe, and all content can be viewed

After using other tabs

  1. URL is still loaded in iframe, but the framed (visible) content has disappeared

  2. Scrolling within the iframe shows the remaining content of the loaded page, but the disappeared content does not return without reloading the URL in the iframe

Note:

This behaviour is only tested in Safari, but any major-browser issue is an issue all the same. This might be a Safari-only fix, or a universal iframe issue.

iframe sandbox security concerns aside, what's going on with the magic disappearing act?

An obvious hacky fix is to have a refresh button for the user to reload the content, but this is far from ideal.

(Tree/path image take from here)

like image 859
Birrel Avatar asked Jun 29 '16 15:06

Birrel


2 Answers

Perhaps it is a redraw/reflow-issue. Its just a weak guess :(

a.style.display='none';
a.offsetHeight;
a.style.display='block';

found here

Try to make a as exact as possible. For testing purposes you can reference the IFrame-body.

More (a lot) information

I am not sure when to redraw at the best. You can test the fix on your mouseenter-handler. Perhaps you can detect the tab-switch by listening on window.onblur and window.onfocus.

like image 76
Andreas Dyballa Avatar answered Nov 16 '22 19:11

Andreas Dyballa


I'm curious if this is happening in all browsers, or just Safari. From the sound of things, it really sounds like a browser bug, and nothing you're doing wrong. Perhaps some RAM optimization that leaves missing pixels as a nasty side effect.

I hope someone comes up with something better, but perhaps a workaround to get you up and running would be to reload the iframe every time the user returns to the tab. Not performant or elagant, but UX over all.

The following code might help mitigate the performance drain.

var url = 'what.com';
var loadURL = function(url) {
  // replace with your function
  console.log(url);
}

function getHiddenProp() {
    var prefixes = ['webkit','moz','ms','o'];
    
    // if 'hidden' is natively supported just return it
    if ('hidden' in document) return 'hidden';
    
    // otherwise loop over all the known prefixes until we find one
    for (var i = 0; i < prefixes.length; i++){
        if ((prefixes[i] + 'Hidden') in document) 
            return prefixes[i] + 'Hidden';
    }

    // otherwise it's not supported
    return null;
}

var isHidden = (function() {
    // I'm using an IIFE here so that getHiddenProp is only run once, when this code inits, instead of ever time the tab changes.
    var prop = getHiddenProp();
    return function() {
        if (!prop) return false;
        return document[prop];
    }
})();

document.addEventListener('visibilitychange', function(){
    if(isHidden() === false) {
        // Wrapping your function in this event listener and this if statement ensures it only runs when the user navigates back to this tab.  There may even be a more performant way of doing this, so poke around if you decide to use this.
        loadURL(url);
    }
});

Note that I gleened the "is tab visible" code from this helpful entry: http://www.html5rocks.com/en/tutorials/pagevisibility/intro/

Hope this helps! Good luck with your endeavors!

like image 45
jmealy Avatar answered Nov 16 '22 18:11

jmealy