Подтвердить что ты не робот

Как переместить iFrame в DOM без потери состояния?

Взгляните на этот простой HTML:

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

Скажем, я хотел переместить обертки так, чтобы #wrap2 был перед #wrap1. Ифрагмы загрязнены 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 изменилась бы, если пользователь щелкнул по телу. Эта переменная и событие click должны оставаться после перемещения iFrame (вместе с любыми другими переменными/событиями, которые были запущены)

Мой вопрос следующий: с JavaScript (с jQuery или без него), как я могу перемещать узлы переноса в DOM (и их дочерние элементы iframe), чтобы окно iFrame оставалось прежним, а события iFrame/variables/etc остаются неизменными?

4b9b3361

Ответ 1

Невозможно переместить iframe из одного места в dom в другое без перезагрузки.

Вот пример, показывающий, что даже с использованием собственного JavaScript iFrames все еще перезагружается: http://jsfiddle.net/pZ23B/

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

Ответ 2

Этот ответ связан с щедростью by @djechlin

Множество поисков по спецификациям w3/dom и не нашли ничего окончательного, что, в частности, говорит о том, что iframe следует перезагружать при перемещении в дереве DOM, однако я нашел много ссылок и комментариев в webkit trac/bugzilla/microsoft относительно различных изменений поведения за эти годы.

Надеюсь, что кто-то найдет что-то конкретное в этом вопросе, но сейчас вот мои выводы:

  • Согласно Ryosuke Niwa - "Это ожидаемое поведение".
  • Был "волшебный iframe" (webkit, 2010), но он был удален в 2012 году.
  • Согласно MS - "ресурсы iframe освобождаются при удалении из DOM". Когда вы appendChild(node) существующего node - то node сначала удаляется из dom.
    Интересная вещь здесь - IE<=8 не перезагружает iframe - это поведение (несколько) новоеIE>=9).
  • В соответствии с Hallvord RM Steen комментарий, это цитата из спецификаций iframe

    Когда элемент iframe вставлен в документ, в котором есть контекст просмотра, пользовательский агент должен создать новый контекст просмотра, установить контекстный контекст просмотра элемента в недавно созданный контекст просмотра, а затем обработать iframe атрибуты для "первого раза" .

    Это самая близкая вещь, которую я нашел в спецификациях, однако она по-прежнему требует некоторой интерпретации (поскольку, когда мы перемещаем элемент iframe в DOM, мы действительно не делаем полного remove, даже если браузеры использует метод node.removeChild).

Ответ 3

Всякий раз, когда iframe добавляется и применяется атрибут src, он запускает действие загрузки аналогично созданию тега изображения через JS. Поэтому, когда вы удаляете и добавляете их, они являются совершенно новыми объектами, и они обновляются. Его тип window.location = window.location перезагрузит страницу.

Единственный способ, которым я знаю, переместить iframes через CSS. Вот пример, который я собрал, показывая один способ справиться с этим с помощью flex-box: https://jsfiddle.net/3g73sz3k/15/

Основная идея - создать обертку flex-box, а затем определить определенный порядок для iframes, используя атрибут 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

Надеюсь, что это поможет.

Ответ 4

Если вы создали iFrame на странице и вам просто нужно переместить его, попробуйте этот подход:

Приложите iFrame к телу и используйте высокий индекс z и верхний, левый, ширина и высоту, чтобы разместить iFrame там, где вы хотите.

Даже CSS-масштабирование работает на теле без перезагрузки, что является удивительным!

Я поддерживаю два состояния для своего "виджета", и он либо вводится на место в DOM, либо в тело, используя этот метод.

Это полезно, когда другой контент или библиотеки будут хлюпать или раздавить ваш iFrame.

BOOM!

Ответ 5

К сожалению, свойство parentNode элемента HTML DOM доступно только для чтения. Конечно, вы можете отрегулировать позиции фреймов, но вы не можете изменить их местоположение в DOM и сохранить свои состояния.

См. этот jsfiddle, который я создал, который обеспечивает хорошую тестовую кровать. http://jsfiddle.net/RpHTj/1/

Нажмите на поле, чтобы переключить значение. Нажмите "move", чтобы запустить javascript.

Ответ 6

Этот вопрос довольно старый... но я нашел способ переместить iframe без его перезагрузки. Только CSS. У меня есть несколько iframe с потоками камеры, мне не нравится, когда они перезагружаются, когда меняют их. Поэтому я использовал комбинацию float, position: absolute и некоторых фиктивных блоков, чтобы перемещать их без перезагрузки и иметь желаемый макет по требованию (изменение размера и все).

Ответ 7

В ответ на щедрость @djechlin, поставленную на этот вопрос, я разветкил jsfiddle, отправленный @matt-h, и пришел к выводу, что это все еще невозможно.

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

Ответ 8

Если вы используете iframe для доступа к страницам, которые вы контролируете, вы можете создать некоторый javascript, чтобы позволить вашему родителю общаться с iframe через postMessage

Оттуда вы можете создать логин внутри iframe для записи изменений состояния, а перед перемещением dom запросите это как объект json.

После перемещения iframe перезагрузится, вы можете передать данные состояния в iframe, и прослушивание iframe может проанализировать данные обратно в предыдущее состояние.