为什么我不能在uninserted节点上使用原型DOM方法呢?

时间:2009-11-10 09:09:06

标签: javascript internet-explorer dom prototypejs

这里的目标是在使用prototypeJs方法将一些DOM节点插入文档之前对它们进行操作。

测试用例:

<html>
<head>
    <script type="text/javascript" src="prototype.js" ></script>
</head>
<body>
    <script type="text/javascript">
        var elt = document.createElement("DIV");
        elt.id="root";
        elt.innerHTML="<div id='stuff'><span id='junk'></span></div>";

        console.info(elt);

        console.info(Element.down(elt, "#stuff"));
        console.info(Element.select(elt, "#stuff"));

        console.info(elt.down("#stuff"));
        console.info(elt.select("#stuff"));

        Element.extend(elt);

        console.info(elt.down("#stuff"));
        console.info(elt.select("#stuff"));

        document.body.appendChild(elt);

        console.info($("root").down("#stuff"));
        console.info($("root").select("#stuff"));

    </script>
</body>
</html>

在Firefox中,所有8个测试都正确输出“stuff”div或仅包含“stuff”div的集合。

在ie(在7/8中测试)我希望后两个测试只会失败,因为原型不像ff那样自动扩展DOM。然而,实际发生的是所有测试直到元素插入失败,两个后续测试都没问题。一旦我调用Element.extend,就会期望down / select方法可用。

如果这种行为如预期的那样,为什么呢?

您如何建议我以跨浏览器友好的方式在内存中的节点上进行DOM遍历?


感谢Kaze no Koe,我把问题缩小了。看来这确实适用于但不适用于id选择器。

<html>
    <head>
        <script type="text/javascript" src="prototype.js" ></script>
    </head>
    <body>
        <script type="text/javascript">     
            var elt = document.createElement("DIV");
            elt.id="root";
            elt.innerHTML="<div id='stuff' class='junk'></div>";
            elt = $(elt);       

            console.info(elt.down("DIV"));      //fine
            console.info(elt.down(".junk"));    //fine
            console.info(elt.down("#stuff"));   //undefined in ie, fine in ff
        </script>
    </body>
</html>

使用class而不是id对我来说不是问题,所以我可以解决我的原始问题,但为了完整起见,任何人都可以解释为什么id选择器在插入之前不会工作,即只是?我的猜测是ie实现依赖于document.getElementById,而ff实现则不依赖于document.getElementById。有谁确认?

2 个答案:

答案 0 :(得分:1)

而不是:

Element.extend(elt);

尝试:

elt = Element.extend(elt);

elt = $(elt);

至于如何在插入节点之前进行遍历,这里有一些随机的例子来说明Prototype的一些特性:

var elt = new Element('div', {
    className: 'someClass'
});

elt.insert(new Element('ul'));

var listitems = ['one', 'two', 'three'];

listitems.each(function(item){
    var elm = new Element('li');
    elm.innerHTML = item;
    elt.down('ul').insert(elm);
});

elt.getElementsBySelector('li'); //=> returns all LIs

elt.down('li'); //=> returns first li

elt.down('ul').down('li'); //=> also returns first li

elt.down('ul').down('li', 2); //=> should return the third if I'm not mistaken

// all before inserting it into the document!

查看brand new API文档。


回答Ollie:上面的代码可以进行测试here,因为你可以看到它在IE 6下工作。

答案 1 :(得分:0)

我认为不可能选择不在文档中的节点,因为选择器依赖于文档节点。

你应该用这种方式建立新的元素:

var elt = new Element("div");