开发者

Why can't i use prototype DOM methods on uninserted nodes in ie?

开发者 https://www.devze.com 2022-12-11 13:32 出处:网络
The goal here is to manipulate some DOM nodes before they are inserted into the document, using prototypeJs methods.

The goal here is to manipulate some DOM nodes before they are inserted into the document, using prototypeJs methods.

Test cases:

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

In Firefox all 8 tests correctly output either the "stuff" div or a collection containing only the "stuff" div.

In ie (tested in 7/8) I would expect the second two tests only to fail as prototype does not automatically extend the DOM as in ff. However what actually happens is all the tests up to the point the element is inserted fail the two subsequent tests are fine. Once I call Element.extend if would expect the down / select methods to be available.

If this behaviour as expected and if so why?

How would you recommend I do my DOM traversal on nodes which are in memory in a cross browser friendly manner?


So thanks to Kaze no Koe, I've narrowed the issue down. It seems that this does work in ie but not for id selectors.

<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>";
         开发者_如何学JAVA   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>

It's not a problem for me to use class instead of id, so I can solve my original issue but for completeness sake can anyone explain why id selectors won't work before insertion in ie only? My guess would be that the ie implementation relies on document.getElementById whilst the ff one doesn't. Anyone confirm?


Instead of:

Element.extend(elt);

Try:

elt = Element.extend(elt);

or

elt = $(elt);

As for how to do the traversing before you've inserted the node, here's some random examples that illustrate a few features of 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!

Check the brand new API documentation.


Answering Ollie: my code above can be tested here, as you can see it works under IE 6.


I don't think it is possible to select nodes that are not in the document, because the selector depends on the document node.

And you should build new elements this way :

var elt = new Element("div");
0

精彩评论

暂无评论...
验证码 换一张
取 消