A quintessential HTML trick for Angularjs - Resizing your iframe

Today, lets talk about "How to resize iframe dynamically?".

Usually setting a fixed frame height is like, asking few 100 people to make a single line queue within a small room. (A mart with only one counter, where the queue comes out of the door).

I faced this specific problem with multi step form which had toggling questions based on the options chosen and options were radio buttons. For example for a question like:

which method you chose to to board the flight?
* Online
* At the desk

Choosing Online opened up a set of questions and similarity for At the desk there were different set of questions. Number of questions varied, so this needed different screen heights.

I went through few questions asked in stackoverflow, which explained complex ways of tackling the problem. None of the answers satisfied the need.

So what I did was, since these toggling happens on click of an option, why not add a click listener on the iframe body and calculate the screen height each time an option was clicked. Though this was overhead as there were over 200 click-able options and each time a click happens the screen height has to be checked. Though there are so many options, users who take the survey may click once or twice for answering question if at all they change their mind to choose a separate option.

You can set the listener like:
element[0].contentWindow.window.document.addEventListener("click", fucntion () {});
where:

  • element[0] points to iframe tag on which directive is used on.
  • contentWindow property returns the Window object generated by an iframe element.Reference
  • window.document is opened document.
  • addEventListener() method attaches an event handler to the specified element.Reference.

Each time a click happens resize() is called which resizes iframe.

Code snippet that has to go within directive that is restricted to 'A'. (More info on directive restictions):

var getAvailableHeight = function () {
    var screenHt = $(window).innerHeight();
    var headerHt = $('header').is(':visible') ? $('header').height() : 0;
    return (screenHt - headerHt);
};

var currentHeight, availableHeight, currentHeightOnClick;

var resize = function () {
    availableHeight = getAvailableHeight();
    element.height(availableHeight);

    if (attrs.resizeIframe !== 'screen') {
        currentHeight = element.contents().find('body').prop('scrollHeight');
        element.height(Math.max(currentHeight, availableHeight));
    }
};

element.load(function() {
    $timeout(resize, 50);
    // On navigation, scroll to top to avoid confusion
    if (element[0].contentWindow && element[0].contentWindow.location) {
        // Listining on click event of the frame to check for dynamic height changes
        element[0].contentWindow.window.document.addEventListener("click", function () {
            // On click calculating height of frame's body
            var currentHeightOnClick = element.contents().find('body').prop('scrollHeight');
            // Setting element height after click
            element.height(Math.max(currentHeight, availableHeight));
            if (currentHeight != currentHeightOnClick) {
                resize();
            }
        });
    }
});

$(window).resize(function () {
    $timeout(resize, 10);
});