23

次のリンクでわかるように、私はiframeを持っています;-

http://one2onecars.com

iframeは、画面中央にあるオンライン予約です。私が抱えている問題は、ページが読み込まれるときにiframeの高さは問題ないが、ページのコンテンツが調整されるときに何らかの方法で高さを自動調整する必要があることです。たとえば、オンライン予約で郵便番号検索を行うと、ドロップダウンメニューが作成され、[次のステップ]ボタンが表示されなくなります。

オンライン予約のコンテンツが変更されると、他のページが読み込まれないため、iframeはiframeの新しい高さに(動的に)自動的に調整されます。

この問題を解決するためにjqueryを使用していくつかの異なるスクリプトを試しましたが、それらはすべて、ページが最初に読み込まれたときにiframeの高さを自動調整するだけであり、iframeのコンテンツが変更されたときではないようです。

これも可能ですか?

私が現在持っているコードは、現時点で設定された高さです:-

        <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

4 に答える 4

31

setInterval

それだけ (ブラウザ技術の進歩により修正されました。DavidBradshawの回答を参照してください) iframeでこれを実現するための下位互換性のある方法は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自体から機能するようにすることができます。

クロスドメインの問題

問題は、ブラウザのセキュリティにより、メインページとは別のホストにある場合はiframeのコンテンツにアクセスできないため、追加する方法がない限り、実際にできることは何もないということです。 iframeに表示されるhtmlへのスクリプト。

ajax

他の何人かは、AJAXを介してサードパーティのサービスを使用することを提案しています。ただし、サービスがこの方法をサポートしていない限り、サービスを機能させることができる可能性はほとんどありません。特に、予約サービスが必要になる可能性が最も高い場合はそうです。 https/sslを介して動作します。

iframeコンテンツを完全に制御できるように見えるので、完全なオプションを利用できます。JSONPを使用したAJAXがオプションになります。しかし、警告の一言。予約システムが多段階である場合、AJAXルートをたどる場合は、適切に設計されたUI(および場合によっては履歴/フラグメント管理コード)があることを確認する必要があります。これは、ユーザーがブラウザで前後に移動するタイミングがわからないためです(iframeが自動的に処理します)。適切に設計されたUIは、ユーザーがこれを行うのを妨げる可能性があります。

クロスドメイン通信

両方の側を制御できる場合(あなたがそうしているように聞こえます)、を使用したクロスドメイン通信オプションもありますwindow.postMessage-詳細については、https://developer.mozilla.org/en-US/docs/DOM/windowを参照してください。 postMessage

于 2013-01-15T09:17:03.390 に答える
26

最新のブラウザーと一部の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');

メッセージを受信するには、メッセージイベントのイベントリスタナーを作成します。

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はその高さを「*」にポストできます。ただし、着信メッセージが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

最新のブラウザのもう1つの進歩は、DOMの変更を監視できるMutationObserverです。そのため、setIntervalで常にポーリングしなくても、iFrameのサイズに影響を与える可能性のある変更を検出できるようになりました。

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の正確な高さを取得することは、チェックできる6つの異なるプロパティの選択肢があり、それらのどれも常に正しい答えを与えないため、本来あるべきほど単純ではありません。私が思いついた最善の解決策は、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バージョンについては、この回答を参照してください。

本文がオーバーフローし、コードを修正してこれを停止できない場合は、offsetHeightまたはscrollHeightのプロパティのいずれかを使用するのdocument.documentElementが最善のオプションです。どちらにも長所と短所があり、両方をテストしてどちらが効果的かを確認するのが最善です。

その他の問題

考慮すべきその他の事項には、ページに複数のiFrameがある、ページのサイズ変更を引き起こすCSS:Checkboxおよび:Hoverイベント、iFrameの本文とhtmlタグでの高さ自動の使用の回避、最後にウィンドウのサイズ変更などがあります。

IFrameリサイザーライブラリ

私はこれらすべてを単純な依存関係のないライブラリにまとめました。これは、ここで説明されていないいくつかの追加機能も提供します。

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

これはIE8+で動作します。

于 2014-04-10T15:08:09.280 に答える
7

私はこのスクリプトを書きました、そしてそれは私のために完全に働いています。お気軽にご利用ください!

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>
于 2013-10-11T06:52:36.750 に答える
0

このスクリプトを使用します。

$(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';
    });
  }
});

注: Webサーバーで使用してください。

于 2013-01-15T09:13:00.207 に答える