通过DOM中的前置元素进行无限循环

use*_*753 3 javascript dom infinite-loop internet-explorer-6

不寻找使用框架XXX答案

这个问题不是为了通过框架找到实际的解决方案.回答使用框架XXX,或者这在框架XXX中是如此简单,或者为什么不使用这个框架XXX ??? 不回答这个问题.

我有一个函数意味着在页面加载后运行:performShim.此函数迭代DOM中作为span标记的所有元素,检查它们是否具有className,shim如果是,则调用shim传递给匹配元素的引用.

我的目标是在前面加上另一个span包含一个iframe以传递的元素shim.

到目前为止我写的代码,我能够附加到元素的父级就好了.但是,如果我注释掉该append行并改为尝试前置行,则浏览器可能会挂起无限循环.

对我来说,为什么会出现这种情况并不容易.

function shim( element ) {      
    var iframe = document.createElement('iframe');
    iframe.setAttribute( 'frameborder', '0' );
    iframe.setAttribute( 'scrolling', 'no' );
    iframe.setAttribute( 'align', 'bottom' );
    iframe.setAttribute( 'marginheight', '0' );
    iframe.setAttribute( 'marginwidth', '0' );
    iframe.setAttribute( 'src', "javascript:'';" ); 

    var span = document.createElement('span');
    span.appendChild(iframe);


    //element.parentNode.insertBefore(span,element); //causes infinite loop?

    element.parentNode.appendChild(span); //this line works OK

    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = 'inline';
    var width = element.offsetWidth;
    var height = element.offsetHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;

    iframe.style.width = (width-6) + 'px';
    iframe.style.height = (height-6) + 'px';

}   

function performShim() {
    var children = document.getElementsByTagName("span");   
    for( var i = 0; i < children.length; i++ ) {
        if( children[i].className == "shim" ) {
            shim(children[i]);  
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)

cHa*_*Hao 8

A NodeList(例如返回的那个document.getElementsByTagName)通常是一个实时列表 - 您对DOM所做的更改也会显示在其中.因此,每次span在当前元素之前添加一个元素时,您将列表扩展一个元素并将当前元素移动一个,然后下一个迭代将您回到刚刚完成的节点.

你有几个简单的解决方法......

  • 添加节点时将计数器压缩. (丑陋,如果你最终添加的东西而不是a span,你最终将跳过节点,这将不明显为什么.)

  • 将列表复制到数组并迭代数组.你可以用
    children = [].slice.call(children, 0);(更常见的)或者类似的东西来做到这一点
    children = Array.apply(window, children);.

  • 使用document.querySelectorAll,返回一个不活动的NodeList.(即使它是实时的,在这种情况下你可以选择'span.shim',插入的跨距也不会显示在其中.)

  • 向后迭代(从children.length - 10到0).

  • +1.*下一次迭代会让你回到刚刚完成的节点上*这是重要的部分.追加是"很好的"(在这种情况下),因为在下一次迭代中,您将处理另一个节点,最终您将使用类"shim"耗尽`span`节点.但是如果生成的`span`s也分配了`shim`类,它也会生成无限循环. (2认同)
  • @ user1169578:看我的评论.关于前置,考虑使用节点"a,b".你的循环变量是`i = 0`.现在你处理`a`并在节点`c`前加上.结果是`c,a,b`.你的循环变量前进到`i = 1`,这又是节点`a` ...等.如果你追加,你的列表可能看起来像'a,b,c`,一旦你处理'c`你赢了不再附加任何节点,因为`c`没有类`shim`. (2认同)