1

We are getting data from the backend and need to write it to an iframe. We have to set the iframe height to the height of the content. We can't get the correct height until the content is actually IN the iframe, which is not instantaneous for a large amount of content. Is there a callback to know when the write is done?

Right now, we have a timer, but it is brittle code:

//data received from backend     
//write data to iframe
//$iframe is a jQuery DOM element 
$iframe[0].contentDocument.open();
$iframe[0].contentDocument.write(data);
$iframe[0].contentDocument.close();

setTimeout(function (){
    var scrollHeight = $iframe.contents().find('body')[0].scrollHeight
            $iframe.css("height", scrollHeight );
}, 1000);
1
  • Have you tried listening for the load event on the iframe? Commented Feb 25, 2017 at 1:38

4 Answers 4

2

Have you tried listening for the load event on the iframe?

var doc = $iframe[0].contentDocument
doc.open()
doc.write(data)
doc.close()

$iframe.on('load', function () {
    this.style.height = doc.body.scrollHeight + 'px'
})
Sign up to request clarification or add additional context in comments.

Comments

0

iframes do have an onload event:

$iframe[0].contentDocument.open();
$iframe[0].contentDocument.write(data);
$iframe[0].contentDocument.close();

$iframe.onload = function() {
  var scrollHeight = $iframe.contents().find('body')[0].scrollHeight
  $iframe.css("height", scrollHeight);
};

Comments

0

Your best option is to use mutationObserver in the iFrame. This is not quite as simple as a callback I'm afraid.

Here's is the code the iFrame-resizer library uses to work this out. You would need to change the line that calls sendSize To call your callback method.

function setupBodyMutationObserver(){
    function addImageLoadListners(mutation) {
        function addImageLoadListener(element){
            if (false === element.complete) {
                console.log('Attach listeners to ' + element.src);
                element.addEventListener('load', imageLoaded, false);
                element.addEventListener('error', imageError, false);
                elements.push(element);
            }
        }

        if (mutation.type === 'attributes' && mutation.attributeName === 'src'){
            addImageLoadListener(mutation.target);
        } else if (mutation.type === 'childList'){
            Array.prototype.forEach.call(
                mutation.target.querySelectorAll('img'),
                addImageLoadListener
            );
        }
    }

    function removeFromArray(element){
        elements.splice(elements.indexOf(element),1);
    }

    function removeImageLoadListener(element){
        console.log('Remove listeners from ' + element.src);
        element.removeEventListener('load', imageLoaded, false);
        element.removeEventListener('error', imageError, false);
        removeFromArray(element);
    }

    function imageEventTriggered(event,type,typeDesc){
        removeImageLoadListener(event.target);
        sendSize(type, typeDesc + ': ' + event.target.src, undefined, undefined);
    }

    function imageLoaded(event) {
        imageEventTriggered(event,'imageLoad','Image loaded');
    }

    function imageError(event) {
        imageEventTriggered(event,'imageLoadFailed','Image load failed');
    }

    function mutationObserved(mutations) {
        sendSize('mutationObserver','mutationObserver: ' + mutations[0].target + ' ' + mutations[0].type);

        //Deal with WebKit asyncing image loading when tags are injected into the page
        mutations.forEach(addImageLoadListners);
    }

    function createMutationObserver(){
        var
            target = document.querySelector('body'),

            config = {
                attributes            : true,
                attributeOldValue     : false,
                characterData         : true,
                characterDataOldValue : false,
                childList             : true,
                subtree               : true
            };

        observer = new MutationObserver(mutationObserved);

        console.log('Create body MutationObserver');
        observer.observe(target, config);

        return observer;
    }

    var
        elements         = [],
        MutationObserver = window.MutationObserver || window.WebKitMutationObserver,
        observer         = createMutationObserver();

    return {
        disconnect: function (){
            if ('disconnect' in observer){
                console.log('Disconnect body MutationObserver');
                observer.disconnect();
                elements.forEach(removeImageLoadListener);
            }
        }
    };
}

Comments

0

maybe postMessage will help you.

var testData = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n';
var $iframe = document.querySelector('#test-iframe');
var $button = document.querySelector('button');

// listen the callback message from iframe
window.self.addEventListener('message', function(ev) {
    if (ev.data && ev.data.status === 'ready') {
        $iframe.style.height = ev.data.height + 'px';
    }
});


$button.addEventListener('click', function() {
    // render content
    $iframe.contentDocument.body.innerText = testData;
    // send message to the top window
    window.self.postMessage({
        status: 'ready',
        height: $iframe.contentDocument.body.scrollHeight
    }, '*');
});
`

https://jsfiddle.net/caoyy/Lb5k13bw/2/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.