상태를 잃지 않고 DOM에서 iFrame을 이동하는 방법은 무엇입니까?


95

이 간단한 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의 창이 동일하게 유지되고 iFrame의 이벤트 / 변수 / 등이 유지되도록 DOM (및 iframe 자식)의 랩 노드를 어떻게 이동할 수 있습니까? 같은?



Mozilla로 발생한 현재 버그 ... bugzilla.mozilla.org/show_bug.cgi?id=254144
Manse

@ManseUK : 다른 질문은별로 도움이되지 않았지만 버그는 꽤 흥미 롭습니다.
JCOC611

1
@SalmanA 어떻게 부모를 아이 "주위"로 이동합니까?
djechlin

1
이 질문은 요소의 목록, 각각의 순서를 변경하는 것이었다 내가 열 때 원하는 효과 웨이 다시 @denodster inline-block이 시점에서 ... 디스플레이를, 나는 일반적인 솔루션을 추측하고있어 (또는 효과적으로 불가능 문이다) 다른 사람들의 관심을 고려할 때 가장 적절할 것입니다.
JCOC611

답변:


46

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

4
글쎄, iFrames가 다시로드되면 옵션이 아닙니다.
JCOC611 2011

3
예의 목적은 네이티브 JavaScript를 사용하더라도 iFrame이 여전히 다시로드된다는 것을 보여주는 것입니다.
Kevin B

글쎄, 사실, 나는 그것이 다시로드되는지 여부는 신경 쓰지 않는다. 그들의 위치는 about:blank.하지만 내가 신경 쓰는 것은 프레임 내부의 내용을 잃는 것입니다.
JCOC611 2011

1
다시로드되면 iframe 내부의 콘텐츠가 손실됩니다. jquery를 사용하여 이동하기 전에 iframe 내부의 내용을 가져올 수 $("#iframeid").contents()있지만 저장된 javascript 데이터를 얻지 못하며 iframe에 의해 상위 페이지로 전송되어야합니다 (또는 상위 페이지에서 가져와야합니다. iframe)
Kevin B

1
DelightedD0D, 현상금은 @djechlin에 의해 개설되었습니다. "2016 년에도 이것이 사실인지 궁금합니다."이 문제와 관련하여 지난 5 년 동안 변경된 사항이 있는지 확인합니다. 이 기간 동안의 변경 사항에 대한 내 답변에서 요약을 확인할 수 있습니다.
Dekel

41

이 답변은 @djechlin의 현상금과 관련이 있습니다.

w3 / dom 사양에 대한 많은 검색과 DOM 트리에서 이동하는 동안 iframe을 다시로드해야한다고 구체적으로 말하는 최종 항목을 찾지 못했지만 웹킷의 trac / bugzilla / microsoft에서 많은 참조와 주석을 찾았습니다. 수년에 걸쳐 다른 행동 변화.

누군가가이 문제와 관련하여 구체적인 내용을 찾을 수 있기를 바라지 만 지금은 여기에 내 결과가 있습니다.

  1. 니와 료스케 에 따르면 - "그것이 예상되는 동작입니다".
  2. "magic iframe"( 웹킷, 2010 )이 있었지만 2012 년제거되었습니다 .
  3. MS에 따르면 " iframe 리소스는 DOM에서 제거되면 해제됩니다 ". 때 appendChild(node)- 기존 노드의 node첫 번째 DOM에서 제거됩니다.
    여기서 재미있는 것은 - IE<=8iframe을 다시로드하지 않았다 -이 동작 입니다 (다소) 새로운 (이후 IE>=9).
  4. Hallvord RM Steen 의견 에 따르면 이것은 iframe 사양 에서 인용 한 것입니다.

    iframe 요소가 브라우징 컨텍스트가있는 문서에 삽입되면 사용자 에이전트는 새 브라우징 컨텍스트를 생성하고 요소의 중첩 브라우징 컨텍스트를 새로 생성 된 브라우징 컨텍스트로 설정 한 다음 "처음으로 iframe 속성을 처리해야합니다. " .

    이것은 내가 스펙에서 찾은 가장 가까운 것이지만 여전히 약간의 해석이 필요 iframe합니다 (DOM 에서 요소를 이동할 때 remove브라우저가 node.removeChild메서드를 사용하더라도 실제로 전체 작업을 수행하지 않기 때문에 ).


7
설명과 함께 반대 투표자의 답변을 주시면 감사하겠습니다.
Dekel

14

iframe이 추가되고 src 속성이 적용될 때마다 JS를 통해 이미지 태그를 만들 때와 비슷하게로드 작업을 실행합니다. 따라서 제거하고 추가하면 완전히 새로운 엔티티이며 새로 고쳐집니다. window.location = window.location페이지를 다시로드하는 방법 입니다.

재배치하는 유일한 방법 iframes은 CSS를 이용하는 것입니다. 다음은이를 처리하는 한 가지 방법을 보여주는 예제입니다 flex-box. 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 질문에서 해결책을 얻었습니다. DIV 위치를 CSS로만 바꿉니다 .

도움이되기를 바랍니다.


1
첫 번째 단락에 대한 현상금 및 img 및 새 엔티티 생성과 유사 함을 설명합니다. 하지 CSS : P
djechlin

매우 간단하고 효과적입니다! 정말 고마워!
Stan

8

페이지에 iFrame을 만들고 나중에 위치를 이동해야하는 경우 다음 방법을 시도해보십시오.

iFrame을 본문에 추가하고 높은 Z- 색인과 상단, 왼쪽, 너비, 높이를 사용하여 원하는 위치에 iFrame을 배치합니다.

CSS 확대 / 축소도 다시로드하지 않고도 본문에서 작동합니다.

나는 내 "위젯"에 대해 두 가지 상태를 유지하며이 방법을 사용하여 DOM 또는 본문에 삽입됩니다.

다른 콘텐츠 나 라이브러리가 iFrame을 찌그러 뜨리거나 찌그러 뜨리는 경우 유용합니다.

팔!


5

불행히도 parentNode HTML DOM 요소 속성은 읽기 전용입니다. 물론 iframe의 위치를 ​​조정할 수 있지만 DOM에서 위치를 변경하고 상태를 유지할 수는 없습니다.

좋은 테스트 베드를 제공하는이 jsfiddle을 참조하십시오. http://jsfiddle.net/RpHTj/1/

상자를 클릭하여 값을 전환하십시오. 자바 스크립트를 실행하려면 "이동"을 클릭하십시오.


4

이 질문은 꽤 오래되었지만 다시로드하지 않고 iframe을 이동하는 방법을 찾았습니다. CSS 만. 카메라 스트림이있는 iframe이 여러 개 있는데 스왑 할 때 다시로드 할 때 마음에 들지 않습니다. 그래서 저는 float, position : absolute 및 일부 더미 블록의 조합을 사용하여 다시로드하지 않고 원하는 레이아웃 (크기 조정 및 모두)없이 이동했습니다.


1
유일한 실행 가능한 옵션처럼 들립니다. 당신이 생각 해낸 전체 솔루션을 게시해야합니다! 다른 사람들을 시작하기위한 최소한의 기본 코드. 감사!
JCOC611

1

이 질문에 대한 현상금 @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);
}

0

iframe을 사용하여 제어하는 ​​페이지에 액세스하는 경우 부모가 postMessage를 통해 iframe과 통신 할 수 있도록 자바 스크립트를 만들 수 있습니다.

거기에서 상태 변경을 기록하기 위해 iframe 내부에 로그인을 빌드하고 dom을 이동하기 전에 json 객체로 요청할 수 있습니다.

이동되면 iframe이 다시로드되고 상태 데이터를 iframe으로 전달할 수 있으며 iframe 수신 대기자는 데이터를 다시 이전 상태로 구문 분석 할 수 있습니다.


물론, 이것은 많은 코드이며, 프레임에 표시 될 모든 데이터를 제어하고 기술적으로 "DOM에서 이동할 때 상태를 유지"하지
Drew Major
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.