如何在不丢失状态的情况下在DOM中移动iFrame?

JCO*_*611 86 javascript iframe jquery dom

看看这个简单的HTML:

<div id="wrap1">
  <iframe id="iframe1"></iframe>
</div>
<div id="warp2">
  <iframe id="iframe2"></iframe>
</div>
Run Code Online (Sandbox Code Playgroud)

让我们说我想移动包裹,以便在#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>
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,variableThatChanges如果用户点击了主体,变量将会改变.移动iFrame后,此变量和click事件应保留(以及已启动的任何其他变量/事件)

我的问题如下:使用JavaScript(有或没有jQuery),我如何移动DOM中的包裹节点(以及它们的iframe子节点),以便iFrame的窗口保持不变,并且iFrame的事件/变量/等保持不变相同?

use*_*654 43

如果没有重新加载,就无法将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);
Run Code Online (Sandbox Code Playgroud)

  • 好吧,如果iFrame重新加载,那么它不是一个选项. (4认同)
  • 是的,该示例的目的是显示即使使用本机JavaScript,iFrame仍然会重新加载. (3认同)

Dek*_*kel 37

这个答案与@djechlin的赏金有关

很多关于w3/dom规范的搜索并没有找到任何特别说明iframe应该在DOM树中移动时重新加载的内容,但是我确实在webkit的trac/bugzilla/microsoft中找到了很多引用和注释.多年来不同的行为变化.

我希望有人能找到关于这个问题的具体内容,但现在我的调查结果如下:

  1. 根据Ryosuke Niwa的说法- "这是预期的行为".
  2. 有一个"神奇的iframe"(webkit,2010),但它在2012年删除了.
  3. 根据MS - " 从DOM中删除iframe资源时释放 ".当您appendChild(node)使用现有节点时 - node首先从dom中删除.
    这里有趣的事情 - IE<=8没有重新加载iframe - 这种行为(有点)是新的(因为IE>=9).
  4. 根据Hallvord RM Steen的评论,这是iframe规范的引用

    当iframe元素插入到具有浏览上下文的文档中时,用户代理必须创建新的浏览上下文,将元素的嵌套浏览上下文设置为新创建的浏览上下文,然后处理"第一次"的iframe属性".

    这是我在规范中发现的最接近的东西,但它仍然需要一些解释(因为当我们移动iframeDOM中的元素时remove,即使浏览器使用该node.removeChild方法,我们也不会真正完整.)

  • 将得到downvoter的回复和解释. (6认同)

小智 13

每当附加iframe并且应用了src属性时,它就会触发加载操作,类似于通过JS创建Image标记时.因此,当您删除然后追加它们时,它们就是全新的实体并且它们会刷新.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>
Run Code Online (Sandbox Code Playgroud)

正如你在JS小提琴中看到的那样,这些order样式是内联的,以简化flip按钮,从而旋转iframes.

我从这个StackOverflow问题中找到了解决方案:仅使用CSS交换DIV位置

希望有所帮助.

  • 第 1 段的赏金并解释它类似于 img 并创建新实体。不是 css :P (2认同)

mat*_*yer 8

如果您已在页面上创建了iFrame,只需稍后移动它的位置,请尝试以下方法:

将iFrame附加到正文并使用高z-index和顶部,左侧,宽度,高度将iFrame放置在您想要的位置.

甚至CSS缩放也可以在没有重新加载的情况下在身体上工作,这太棒了!

我为我的"小部件"维护了两种状态,它使用此方法注入到DOM中或身体中.

当其他内容或库会挤压或挤压您的iFrame时,此功能非常有用.

繁荣!


Mat*_*t H 5

不幸的是,parentNodeHTML DOM元素的属性是只读的.当然,您可以调整iframe的位置,但不能更改它们在DOM中的位置并保留其状态.

看到我创建的这个jsfiddle提供了一个很好的测试床.http://jsfiddle.net/RpHTj/1/

单击该框以切换值.单击"移动"以运行javascript.


moe*_*ool 5

这个问题已经很老了......但我确实找到了一种在不重新加载的情况下移动 iframe 的方法。仅 CSS。我有多个带有相机流的 iframe,我不喜欢当我交换它们时它们重新加载。因此,我使用了浮动、位置:绝对和一些虚拟块的组合来移动它们,而无需重新加载它们并根据需要获得所需的布局(调整大小等)。