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

时间:2012-03-14 20:00:31

标签: javascript dom internet-explorer-6 infinite-loop

不寻找使用框架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]);  
        }
    }
} 

1 个答案:

答案 0 :(得分:8)

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

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

  • 在添加节点时将计数器搞砸。(丑陋,如果你最终添加的东西而不是span,你最终会跳过节点和为什么不明显。)

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

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

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