Pregunta ¿Cómo mover un iFrame en el DOM sin perder su estado?


Mire este simple HTML:

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

Digamos que quería mover las envolturas para que el #wrap2 sería antes de la #wrap1. Los iframes están contaminados por JavaScript. Estoy enterado de jQuery's .insertAfter() y .insertBefore(). Sin embargo, cuando los utilizo, iFrame pierde todas sus variables y eventos HTML y JavaScript.

Digamos que lo siguiente fue el HTML del iFrame:

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

En el código anterior, la variable variableThatChanges cambiaría ... si el usuario hiciera clic en el cuerpo. Esta variable y el evento de clic deben permanecer después de mover el iFrame (junto con cualquier otra variable / evento que se haya iniciado)

Mi pregunta es la siguiente: con JavaScript (con o sin jQuery), ¿cómo puedo mover los nodos wrap en el DOM (y sus hijos iframe) para que la ventana del iFrame permanezca igual, y los eventos / variables / etc del iFrame permanezcan igual?


74
2017-11-29 21:53


origen


Respuestas:


No es posible mover un iframe de un lugar en el dom a otro sin que se vuelva a cargar.

Aquí hay un ejemplo para mostrar que incluso usando JavaScript nativo, los iFrames aún se vuelven a cargar: http://jsfiddle.net/pZ23B/

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

37
2017-11-29 22:06



Esta respuesta está relacionada con la recompensa de @djechlin

Mucha búsqueda en las especificaciones w3 / dom y no encontré nada definitivo que diga específicamente que el iframe debe ser recargado mientras se mueve en el árbol DOM, sin embargo encontré muchas referencias y comentarios en el trak / bugzilla / microsoft del webkit diferentes cambios de comportamiento a lo largo de los años.

Espero que alguien encuentre algo específico sobre este tema, pero por ahora estos son mis hallazgos:

  1. De acuerdo a Ryosuke Niwa - "Ese es el comportamiento esperado".
  2. Hubo un "iframe mágico" (webkit, 2010), pero fue eliminado en 2012.
  3. De acuerdo con MS - "los recursos iframe se liberan cuando se eliminan del DOM". Cuando tú appendChild(node) del nodo existente - eso node primero se elimina de la dom.
    Algo interesante aquí - IE<=8 no recargó el iframe - este comportamiento es (algo) nuevo (ya que IE>=9)
  4. De acuerdo a Hallvord R. M. Steen comentar, esta es una cita de especificaciones iframe

    Cuando se inserta un elemento de marco flotante en un documento que tiene un contexto de exploración, el agente de usuario debe crear un nuevo contexto de exploración, establecer el contexto de exploración anidada del elemento en el contexto de exploración recién creado, y luego procesar los atributos del iframe para la "primera vez".

    Esta es la cosa más cercana que encontré en las especificaciones, sin embargo, todavía requiere alguna interpretación (ya que cuando movemos el iframe elemento en el DOM que realmente no hacemos un completo remove, incluso si los navegadores usan node.removeChild método).


25
2017-10-06 11:59



Cada vez que se agrega un iframe y se aplica un atributo src, se activa una acción de carga de forma similar a cuando se crea una etiqueta Image a través de JS. Entonces, cuando los quita y los agrega, son entidades completamente nuevas y se actualizan. Es como que window.location = window.locationrecargará una página.

La única forma en que sé reposicionar iframes es a través de CSS. Aquí hay un ejemplo que reuní mostrando una forma de manejar esto con flex-box: https://jsfiddle.net/3g73sz3k/15/

La idea básica es crear un flex-box envoltorio y luego definir un orden específico para los iframes utilizando el atributo de orden en cada envoltorio 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>

Como puedes ver en el violín JS estos order los estilos están en línea para simplificar el flip botón para rotar el iframes.

Recurrí a la solución de esta pregunta de StackOverflow: Cambiar posición DIV con CSS solamente

Espero que ayude.


10
2017-10-12 11:46



Si ha creado el iFrame en la página y simplemente necesita mover su posición más tarde, pruebe este enfoque:

Agregue el iFrame al cuerpo y use un alto índice Z y arriba, izquierda, ancho y alto para colocar el iFrame donde desee.

Incluso el zoom CSS funciona en el cuerpo sin recargar, ¡lo cual es increíble!

Mantengo dos estados para mi "widget" y se inyecta en el DOM o en el cuerpo utilizando este método.

Esto es útil cuando otro contenido o bibliotecas aplastan o aplastan su iFrame.

¡AUGE!


5
2018-04-15 17:25



Desafortunadamente, el parentNode la propiedad de un elemento HTML DOM es de solo lectura. Puede ajustar las posiciones de los iframes, por supuesto, pero no puede cambiar su ubicación en el DOM y preservar sus estados.

Ver este jsfiddle que creé que proporciona una buena cama de prueba. http://jsfiddle.net/RpHTj/1/

Haga clic en el cuadro para alternar el valor. Haga clic en "mover" para ejecutar el javascript.


4
2017-11-29 22:26



Esta pregunta es bastante antigua ... pero encontré una forma de mover un iframe sin que se recargara. CSS solo Tengo múltiples iframes con secuencias de cámara, no me gusta cuando se vuelven a cargar cuando los cambio. Así que utilicé una combinación de float, position: absolute y algunos bloques ficticios para moverlos sin recargarlos y tener el diseño deseado bajo demanda (cambio de tamaño y todo).


4
2018-06-17 18:52



En respuesta al bounty @djechlin puesto en esta pregunta, he bifurcado el jsfiddle publicado por @ matt-h y he llegado a la conclusión de que esto aún no es posible.

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
2017-10-11 16:21



Si está utilizando el iframe para acceder a las páginas que controla, puede crear algunos javascript para permitir que sus padres se comuniquen con el iframe a través de postMessage.

A partir de ahí, puede crear un inicio de sesión dentro del iframe para registrar los cambios de estado, y antes de mover el dom, solicítelo como un objeto json.

Una vez movido, el iframe se volverá a cargar, puede pasar los datos de estado al iframe y el iframe que escucha puede analizar los datos nuevamente en el estado anterior.


0
2017-10-12 16:06