web-dev-qa-db-ja.com

状態を失わずにDOMでiFrameを移動する方法は?

この単純なHTMLを見てください。

_<div id="wrap1">
  <iframe id="iframe1"></iframe>
</div>
<div id="warp2">
  <iframe id="iframe2"></iframe>
</div>
_

_#wrap2_が_#wrap1_の前になるようにラップを移動したいとしましょう。 iframeはJavaScriptによって汚染されています。 jQueryの.insertAfter().insertBefore()を知っています。ただし、これらを使用すると、iFrameはHTML、JavaScriptの変数とイベントをすべて失います。

以下がiFrameのHTMLであったとしましょう:

_<html>
  <head>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
      // The variable below would change on click
      // This represents changes on variables after the code is loaded
      // These changes should remain after the iFrame is moved
      variableThatChanges = false;
      $(function(){
        $("body").click(function(){ 
          variableThatChanges = true; 
        });
      });
    </script>
  </head>
  <body>
    <div id='anything'>Illustrative Example</div>
  </body>
</html>
_

上記のコードでは、ユーザーが本文をクリックすると、変数variableThatChangesが変更されます。この変数とクリックイベントは、iFrameを移動した後も(開始されている他の変数/イベントと一緒に)残る必要があります

私の質問は次のとおりです:JavaScript(jQueryの有無にかかわらず)、iFrameのウィンドウが同じままになるようにDOM(およびそのiframeの子)でラップノードを移動する方法iFrameのイベント/変数などは同じままですか?

84
JCOC611

Iframeをリロードせずにdomのある場所から別の場所に移動することはできません。

ネイティブJavaScriptを使用してもiFrameがまだリロードされることを示す例を次に示します。 http://jsfiddle.net/pZ23B/

var wrap1 = document.getElementById('wrap1');
var wrap2 = document.getElementById('wrap2');
setTimeout(function(){
    document.getElementsByTagName('body')[0].appendChild(wrap1);
},10000);
42
Kevin B

この回答は、@ djechlinによる賞金に関連しています

W3/dom仕様の多くの検索で、DOMツリー内で移動中にiframeをリロードする必要があることを具体的に示す最終的なものは見つかりませんでしたが、Webkitのtrac/bugzilla/Microsoftで多くの参照とコメントを見つけました長年にわたってさまざまな行動が変化します。

誰かがこの問題に関する具体的な何かを見つけることを望んでいますが、今のところは私の発見です:

  1. 丹羽亮介 -「これが予想される動作」によると。
  2. 「マジックiframe」がありました( webkit、201 )が、それは 2012年に削除されました です。
  3. MSによれば-" iframeリソースはDOMから削除されると解放されます 。既存のノードのappendChild(node)の場合-nodeが最初にdomから削除されます。
    ここで興味深いこと-​​IE<=8はiframeをリロードしませんでした-この動作は(多少)newIE>=9)。
  4. Hallvord R. M. Steen コメントによると、これは iframe specs からの引用です

    ブラウジングコンテキストを含むドキュメントにiframe要素が挿入されると、ユーザーエージェントは新しいブラウジングコンテキストを作成し、要素のネストされたブラウジングコンテキストを新しく作成されたブラウジングコンテキストに設定し、 「初回」のiframe属性を処理します

    これは私が仕様で見つけた最も近いものですが、まだいくつかの解釈が必要です(DOMでiframe要素を移動すると、完全なremoveを実行しないため、ブラウザがnode.removeChildメソッドを使用している場合)。

36
Dekel

Iframeが追加され、src属性が適用されている場合は常に、JSを介してImageタグを作成する場合と同様にロードアクションを実行します。したがって、それらを削除してから追加すると、それらは完全に新しいエンティティになり、更新されます。 window.location = window.locationがページをリロードする方法。

iframesの位置を変更する唯一の方法は、CSSを使用することです。 flex-boxでこれを処理する1つの方法を示した例を以下に示します。 https://jsfiddle.net/3g73sz3k/15/

基本的な考え方は、flex-boxラッパーを作成し、各iframeラッパーのorder属性を使用してiframeの特定の順序を定義することです。

<style>
  .container{
    display: flex;
    flex-direction: column;
  }
</style>
<div class="container">
  <div id="wrap1" style="order: 0" class="iframe-wrapper">
    <iframe id="iframe1" src="https://google.com"></iframe>
  </div>
  <div id="warp2" style="order: 1" class="iframe-wrapper">
    <iframe id="iframe2" src="https://bing.com"></iframe>
  </div>
</div>

JSフィドルでわかるように、これらのorderスタイルはflipボタンを単純化するためにインラインであるため、iframesを回転させます。

このStackOverflowの質問からソリューションを入手しました: CSSのみでDIVの位置を入れ替える

お役に立てば幸いです。

13
PaulSCoder

ページ上にiFrameを作成し、後でその位置を移動する必要がある場合は、このアプローチを試してください。

IFrameを本文に追加し、高いz-indexとtop、left、width、heightを使用して、iFrameを目的の場所に配置します。

CSSズームでさえ、リロードせずにボディで機能します。

私は「ウィジェット」の2つの状態を維持し、このメソッドを使用してDOMの所定の位置またはボディに注入します。

これは、他のコンテンツまたはライブラリがiFrameをつぶしたりつぶしたりする場合に便利です。

ブーム!

8
mattdlockyer

残念ながら、HTML DOM要素のparentNodeプロパティは読み取り専用です。もちろん、iframeの位置を調整することはできますが、DOM内の位置を変更して状態を保持することはできません。

良いテストベッドを提供する、私が作成したこのjsfiddleを参照してください。 http://jsfiddle.net/RpHTj/1/

ボックスをクリックして値を切り替えます。 「移動」をクリックしてjavascriptを実行します。

5
Matt H

この質問はかなり古いものですが、リロードせずにiframeを移動する方法を見つけました。 CSSのみ。カメラストリームを含む複数のiframeがあり、それらをスワップするときにリロードするのが好きではありません。そこで、フロート、position:absolute、およびいくつかのダミーブロックの組み合わせを使用して、リロードせずに必要なレイアウト(サイズ変更およびすべて)を行わずにそれらを移動しました。

4
moeiscool

この質問に対する@djechlinの賞金に応えて、@ matt-hが投稿したjsfiddleを分岐し、これはまだ不可能であるという結論に達しました。

http://jsfiddle.net/gr3wo9u6/

//this does not work, the frames reload when appended back to the DOM
function swapFrames() {
    var w1 = document.getElementById('wrap1');
    var w2 = document.getElementById('wrap2');
    var f1 = w1.querySelector('iframe');
    var f2 = w2.querySelector('iframe');

    w1.removeChild(f1);
    w2.removeChild(f2);
    w1.appendChild(f2);
    w2.appendChild(f1);
    //f1.parentNode = w2;
    //f2.parentNode = w1;

    //alert(f1.parentNode.id);
}
1
denodster

Iframeを使用して制御するページにアクセスしている場合、javascriptを作成して、親がpostMessage経由でiframeと通信できるようにすることができます。

そこから、iframe内にログインを構築して状態の変更を記録し、domを移動する前に、jsonオブジェクトとして要求します。

移動すると、iframeがリロードされ、状態データをiframeに渡すことができ、iframeリスニングはデータを解析して以前の状態に戻すことができます。

0
Drew Major