iframe随着内容的变化自动调整高度 [英] iframe Auto Adjust Height as content changes

查看:62
本文介绍了iframe随着内容的变化自动调整高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 iframe,您可以在以下链接中看到;-

http://one2onecars.com

iframe 是屏幕中央的在线预订.我遇到的问题是,虽然 iframe 的高度在页面加载时没问题,但我需要它在页面内容调整时以某种方式自动调整高度.例如,如果我在在线预订中进行邮政编码搜索,它会创建一个下拉菜单,然后使下一步"按钮不可见.

我需要做的是,当在线预订的内容发生变化时,iframe 会自动调整到 iframe 的新高度(动态),因为它不会加载任何其他页面.

我使用 jquery 尝试了几个不同的脚本来尝试解决这个问题,但它们似乎都只在页面第一次加载时自动调整 iframe 的高度,不是作为 iframe 的内容变化.

这甚至可以做到吗?

我目前拥有的代码目前具有设定的高度:-

 

<iframe id="main-online-frame" class="booking-dimensions" src="http://www.marandy.com/one2oneob/login-guest.php" scrolling="no" frameborder="0"></iframe>

#main-online-booking {高度:488px;边框底部:6px #939393 实心;左边框:6px #939393 实心;右边框:6px #939393 实心;z-索引:4;背景色:#fff;}.booking-dimensions {宽度:620px;高度:488px;}

如果有人能帮我解决这个问题,我将不胜感激!

解决方案

现代浏览器和部分 IE8 有一些新功能,使这项任务比以前更容易.

发布消息

postMessage API 提供了一种简单的方法在 iFrame 与其父级之间进行通信.

要向父页面发送消息,请按如下方式调用它.

parent.postMessage('Hello parent','http://origin-domain.com');

在另一个方向,我们可以使用以下代码将消息发送到 iFrame.

var iframe = document.querySelector('iframe');iframe.contentWindow.postMessage('你好我的孩子', 'http://remote-domain.com:8080');

要接收消息,请为消息事件创建一个事件监听器.

function receiveMessage(event){if (event.origin !== "http://remote-domain.com:8080")返回;控制台日志(事件数据);}if ('addEventListener' in window){window.addEventListener('message', receiveMessage, false);} else if ('attachEvent' in window){//IEwindow.attachEvent('onmessage', receiveMessage);

这些示例使用 origin 属性来限制消息发送到的位置并检查消息的来源.可以指定 * 以允许发送到任何域,并且在某些情况下您可能希望接受来自任何域的消息.但是,如果您这样做,您需要考虑安全隐患并对传入的消息实施您自己的检查以确保它包含您期望的内容.在这种情况下,iframe 可以将其高度发布到*",因为我们可能有多个父域.但是,检查传入的消息是否来自 iFrame 是个好主意.

function isMessageFromIFrame(event,iframe){无功起源 = event.origin,src = iframe.src;if ((''+origin !=='null') && (origin !== src.substr(0,origin.length))) {抛出新错误('收到来自:'+来源+的意外消息' 为 ' + iframe.id + '.消息是:' + event.data);}返回真;}

突变观察者

更现代的浏览器的另一个进步是MutationObserver,它允许您观察 DOM 的变化;因此,现在可以检测可能影响 iFrame 大小的更改,而无需经常使用 setInterval 进行轮询.

function createMutationObserver(){无功target = document.querySelector('body'),配置 = {属性:真,属性旧值:假,字符数据:真,characterDataOldValue : 假,childList : 真,子树:真},观察者 = 新的 MutationObserver(function(mutations) {parent.postMessage('[iframeResize]'+document.body.offsetHeight,'*');});log('设置突变观察者');观察者.观察(目标,配置);}var MutationObserver = window.MutationObserver ||window.WebKitMutationObserver;如果(突变观察者){createMutationObserver();}

计算出准确的高度

获得 iFrame 的准确高度并不像它应该的那么简单,因为您可以选择六种不同的属性来检查,但没有一个能始终给出正确的答案.我想出的最好的解决方案是,只要您不使用 CSS 溢出 body 标签,这个函数就可以工作.

function getIFrameHeight(){函数 getComputedBodyStyle(prop) {返回 parseInt(document.defaultView.getComputedStyle(document.body, null),10);}返回 document.body.offsetHeight +getComputedBodyStyle('marginTop') +getComputedBodyStyle('marginBottom');}

这是 IE9 版本,对于很长的 IE8 版本,请参阅此 答案.

如果您确实溢出了主体并且无法修复代码以阻止这种情况发生,则使用 document.documentElement 的 offsetHeightscrollHeight 属性 是你最好的选择.两者都有优点和缺点,最好只是测试一下,看看哪个适合你.

其他问题

其他需要考虑的事情包括,页面上有多个 iFrame,CSS :Checkbox 和 :Hover 事件导致页面调整大小,避免在 iFrame 的 body 和 html 标签中使用自动高度,最后调整窗口大小.

IFrame Resizer 库

我已经将所有这些都封装在一个简单的无依赖库中,该库还提供了一些此处未讨论的额外功能.

https://github.com/davidjbradshaw/iframe-resizer

这适用于 IE8+.

I have an iframe as you can see on the following link;-

http://one2onecars.com

The iframe is the online booking in the centre of the screen. The problem I have is that although the height of the iframe is okay as the page loads, I need it to somehow auto adjust the height as the page content adjusts. For example, if I do a postcode search in the online booking it creates a dropdown menu and then makes the 'Next Step' button not viewable.

What I need to happen is that when the content of the online booking changes, the iframe auto adjusts to the new height of the iframe (dynamically) as it is not loading any other pages.

I have tried several different scripts using jquery to try resolving this issue, but they all only seem to auto adjust the height of the iframe when the page first loads and not as the contents of the iframe changes.

Is this even possible to do?

The code I have at the moment is with a set height at the moment:-

        <div id="main-online-booking">

            <iframe id="main-online-frame" class="booking-dimensions" src="http://www.marandy.com/one2oneob/login-guest.php" scrolling="no" frameborder="0"></iframe>

        </div>

#main-online-booking {
    height: 488px;
    border-bottom: 6px #939393 solid;
    border-left: 6px #939393 solid;
    border-right: 6px #939393 solid;
    z-index: 4;
    background-color: #fff;
}


.booking-dimensions {
    width: 620px;
    height: 488px;
}

If anybody can help me with this I would be much appreciated!

解决方案

Modern browser and in part IE8 have some new features that make this task easier than it use to be.

PostMessage

The postMessage API provides a simple method for comunicating between an iFrame and it's parent.

To send a message to the parent page you call it as follows.

parent.postMessage('Hello parent','http://origin-domain.com');

In the other direction we can send the message to the iFrame with the following code.

var iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage('Hello my child', 'http://remote-domain.com:8080');

To recevie a message create an event listerner for the message event.

function receiveMessage(event)
{
  if (event.origin !== "http://remote-domain.com:8080")
    return;

  console.log(event.data);
}

if ('addEventListener' in window){
    window.addEventListener('message', receiveMessage, false);
} else if ('attachEvent' in window){ //IE
    window.attachEvent('onmessage', receiveMessage);

These examples uses the origin property to limit where the message is sent to and to check where it came from. It is possible to specify * to allow sending to any domain and you may in some cases you may want to accept messages from any domain. However, if you do this you need to consider the security implications and implement your own checks on the incoming message to ensure it contains what your expecting. In this case the iframe can post it's height to '*', as we might have more than one parent domain. However, it's a good idea to check incoming messages are from the iFrame.

function isMessageFromIFrame(event,iframe){
    var
        origin  = event.origin,
        src     = iframe.src;

    if ((''+origin !== 'null') && (origin !== src.substr(0,origin.length))) {
        throw new Error(
            'Unexpect message received from: ' + origin +
            ' for ' + iframe.id + '. Message was: ' + event.data  
        );
    }

    return true;
}

MutationObserver

The other advance in more modern broswers is MutationObserver which allows you to watch for changes in the DOM; so it is now possible to detect changes that could effect the size of the iFrame without having to constantly poll with setInterval.

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

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

        observer = new MutationObserver(function(mutations) {
            parent.postMessage('[iframeResize]'+document.body.offsetHeight,'*');
        });

    log('Setup MutationObserver');
    observer.observe(target, config);
}

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

if (MutationObserver){
    createMutationObserver();
}

Working out an accurate height

Getting an accurate height for the iFrame is not as simple as it should be, as you have a choice of six different properties that you can check and none of them give a constantly right answer. The best solution I've come up with is this function that works so long as you don't use CSS to overflow the body tag.

function getIFrameHeight(){
    function getComputedBodyStyle(prop) {
        return parseInt(
            document.defaultView.getComputedStyle(document.body, null),
            10
        );
    }

    return document.body.offsetHeight +
        getComputedBodyStyle('marginTop') +
        getComputedBodyStyle('marginBottom');
}

This is the IE9 version, for the much long IE8 version see this answer.

If you do overflow the body and you can't fix your code to stop this, then using either the offsetHeight or scrollHeight properties of document.documentElement are your best options. Both have pros and cons and it best just to test both and see which works for you.

Other issues

Other things to consider include, having more than one iFrame on the page, CSS :Checkbox and :Hover events causing page resize, avoiding the use of height auto in the iFrames' body and html tags and lastly the window being resized.

IFrame Resizer Library

I've wrapped all this up in a simple dependancy free library, that also provides some extra functions not discussed here.

https://github.com/davidjbradshaw/iframe-resizer

This works with IE8+.

这篇关于iframe随着内容的变化自动调整高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆