Почему я не могу использовать прототипные методы DOM на неустановленных узлах в ie? - PullRequest
1 голос
/ 10 ноября 2009

Целью здесь является манипулирование некоторыми узлами DOM до их вставки в документ с использованием методов prototypeJs.

Контрольные примеры:

<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 тестов правильно выводят либо div «stuff», либо коллекцию, содержащую только div «stuff».

В ie (протестировано в 7/8) я ожидаю, что вторые два теста потерпят неудачу, поскольку прототип не расширяет DOM автоматически, как в ff. Однако, что на самом деле происходит, так это то, что все тесты до того момента, когда элемент вставлен, проваливаются, два последующих теста в порядке. Однажды я вызываю Element.extend, если ожидал, что будут доступны методы down / select.

Если это поведение, как и ожидалось, и если да, то почему?

Как бы вы посоветовали мне выполнять обход DOM на узлах, находящихся в памяти, в кросс-браузерной манере?


Так что благодаря Kaze no Koe я сузил проблему. Кажется, что это работает, то есть, но не для селекторов идентификаторов.

<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, то есть? Я думаю, что реализация ie опирается на document.getElementById, а ff - нет. Кто-нибудь подтвердит?

Ответы [ 2 ]

1 голос
/ 10 ноября 2009

Вместо:

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!

Ознакомьтесь с новой документацией API.


Отвечая Олли: мой код выше можно проверить здесь , как вы можете видеть, он работает в IE 6.

0 голосов
/ 10 ноября 2009

Я не думаю, что можно выбрать узлы, которых нет в документе, потому что селектор зависит от узла документа.

И вы должны создавать новые элементы следующим образом:

var elt = new Element("div");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...