首页 文章

iframe在内容更改时自动调整高度

提问于
浏览
18

我可以在以下链接中看到iframe; -

http://one2onecars.com

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

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

我已尝试使用jquery尝试解决此问题的几个不同的脚本,但它们似乎只在页面首次加载时自动调整iframe的高度,并且随着iframe内容的更改而自动调整 not .

这甚至可以做到吗?

我目前的代码目前有一个设定的高度: -

<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;
}

如果有人可以帮助我,我将不胜感激!

4 回答

  • 0

    我写了这个脚本,它对我来说非常合适 . 随意使用它!

    function ResizeIframeFromParent(id) {
        if (jQuery('#'+id).length > 0) {
            var window = document.getElementById(id).contentWindow;
            var prevheight = jQuery('#'+id).attr('height');
            var newheight = Math.max( window.document.body.scrollHeight, window.document.body.offsetHeight, window.document.documentElement.clientHeight, window.document.documentElement.scrollHeight, window.document.documentElement.offsetHeight );
            if (newheight != prevheight && newheight > 0) {
                jQuery('#'+id).attr('height', newheight);
                console.log("Adjusting iframe height for "+id+": " +prevheight+"px => "+newheight+"px");
            }
        }
    }
    

    你可以在循环中调用函数:

    <script>
    jQuery(document).ready(function() {
        // Try to change the iframe size every 2 seconds
        setInterval(function() {
            ResizeIframeFromParent('iframeid');
        }, 2000);
    });
    </script>
    
  • 22

    setInterval

    唯一(由于浏览器技术的进步,请参见David Bradshaw's answer)向后兼容的方式来实现这一点,使用 setInterval 并自己关注iframe的内容 . 当它更改其高度时,您将更新iframe的大小 . 没有这样的事件,你可以倾听,这将很容易让人感到轻松 .

    一个基本示例,这仅在大小已更改的iframe内容是主页面流的一部分时才有效 . 如果元素浮动或定位,那么您将必须专门定位它们以寻找高度变化 .

    jQuery(function($){
      var lastHeight = 0, curHeight = 0, $frame = $('iframe:eq(0)');
      setInterval(function(){
        curHeight = $frame.contents().find('body').height();
        if ( curHeight != lastHeight ) {
          $frame.css('height', (lastHeight = curHeight) + 'px' );
        }
      },500);
    });
    

    显然,根据您的需要,您可以修改此代码的透视图,使其从iframe开始工作,而不是期望成为主页的一部分 .

    cross-domain issue

    你会发现问题是,由于浏览器的安全性,它不会让你访问iframe的内容,如果它在主页的不同主机上,所以除非你有办法添加,否则你实际上没有任何东西可以做任何出现在iframe中的html脚本 .

    ajax

    其他一些人建议尝试通过AJAX使用第三方服务,除非服务支持这种方法,否则你很可能无法使用它 - 特别是如果它是一个很可能需要的预订服务通过https / ssl进行操作 .

    由于您可以完全控制iframe内容,因此您可以选择完整的选项,使用带有JSONP的AJAX . 但是,一句警告 . 如果你的预订系统是多步的,你需要确保你有一个设计良好的用户界面 - 可能还有一些历史/片段管理代码 - 如果你要沿着AJAX路线走下去 . 所有这些都是因为你永远无法分辨用户何时决定在他们的浏览器中向前或向后导航(iframe将在合理范围内自动处理) . 设计良好的UI可以减少用户的操作 .

    cross-domain communication

    如果您可以控制双方(听起来像你这样做),您还可以使用 window.postMessage 进行跨域通信选项 - 有关详细信息,请参阅此处https://developer.mozilla.org/en-US/docs/DOM/window.postMessage

  • 18

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

    PostMessage

    postMessage API提供了一种简单的方法,用于在iFrame和它的父级之间进行通信 .

    要将消息发送到父页面,请按以下方式调用它 .

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

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

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

    要接收消息,请为消息事件创建事件listerner .

    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);
    

    这些示例使用origin属性来限制发送消息的位置并检查消息的来源 . 可以指定 * 以允许发送到任何域,在某些情况下,您可能希望接受来自任何域的邮件 . 但是,如果您这样做,您需要考虑安全隐患,并对传入的消息实施您自己的检查,以确保它包含您期望的内容 . 在这种情况下,iframe可以发布它's height to ' * ', as we might have more than one parent domain. However, it'一个好主意来检查来自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

    更现代的broswers的另一个进步是MutationObserver,它允许你观察DOM的变化;因此,现在可以检测可能影响iFrame大小的更改,而无需使用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();
    }
    

    计算出准确的高度

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

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

    这是IE9版本,对于很长的IE8版本,请看answer .

    如果你身体溢出,你无法修复你的身体停止此操作的代码,然后使用 document.documentElementoffsetHeightscrollHeight 属性是您的最佳选择 . 两者都有利弊,最好只测试两者,看看哪些适合你 .

    其他问题

    其他需要考虑的事项包括:在页面上有多个iFrame,CSS:Checkbox和:悬停事件导致页面调整大小,避免在iFrames的body和html标签中使用height auto,最后调整窗口大小 .

    IFrame Resizer Library

    我把所有这些都包含在一个简单的无需依赖的库中,它还提供了一些未在此讨论的额外功能 .

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

    这适用于IE8 .

  • 7

    使用这个脚本:

    $(document).ready(function () {
      // Set specific variable to represent all iframe tags.
      var iFrames = document.getElementsByTagName('iframe');
    
      // Resize heights.
      function iResize() {
        // Iterate through all iframes in the page.
        for (var i = 0, j = iFrames.length; i < j; i++) {
        // Set inline style to equal the body height of the iframed content.
          iFrames[i].style.height = iFrames[i].contentWindow.document.body.offsetHeight + 'px';
        }
      }
    
     // Check if browser is Safari or Opera.
     if ($.browser.safari || $.browser.opera) {
        // Start timer when loaded.
        $('iframe').load(function () {
        setTimeout(iResize, 0);
        });
    
       // Safari and Opera need a kick-start.
       for (var i = 0, j = iFrames.length; i < j; i++) {
         var iSource = iFrames[i].src;
         iFrames[i].src = '';
         iFrames[i].src = iSource;
       }
     } else {
        // For other good browsers.
        $('iframe').load(function () {
        // Set inline style to equal the body height of the iframed content.
        this.style.height = this.contentWindow.document.body.offsetHeight + 'px';
        });
      }
    });
    

    Note : 在网络服务器上使用它 .

相关问题