getElementsByClassName возвращает [] вместо асинхронного добавленного узла - PullRequest
3 голосов
/ 30 сентября 2011

(Я задаю свой вопрос снова после того, как первый был ужасно сформулирован)

Я сталкиваюсь со следующей проблемой:

<div class="testA" id="test1"></div>

Вышеуказанный письменный элемент предопределен.Теперь я загружаю дерево xml через XMLHttpRequest & Co. , получая следующий ответ:

<response>
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</response>

Теперь я добавляю первый div, используя

request.responseXML.getElementsByTagName("response")[0]
                       .getElementsByTagName("div")[0]

впредопределенный div

<div class="testA" id="test1">

Итоговый документ выглядит следующим образом (проверено с помощью инструментов разработки):

<div class="testA" id="test1">
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</div>

Когда я сейчас пытаюсь получить элемент <div class="colorSelector" id="0-0">, используя getElementById("0-0") Я получаю ожидаемый результат.

Но с использованием getElementsByClassName("colorSelector") возвращает [].

Я что-то пропустил?Возможно, это пережиток того, что узлы были типа Element, а не HTMLElement?

Ответы [ 6 ]

3 голосов
/ 30 сентября 2011

colorSelector закомментировано. JavaScript работает только в DOM, а закомментированные части отсутствуют в DOM.

1 голос
/ 30 сентября 2011

Поскольку вы сказали, что ваш getElementById("0-0") успешен, то, очевидно, у вас нет закомментированных узлов.

Полагаю, вы делаете:

document.getElementById("0-0").getElementsByClassName('colorSelector');

... который не будет работать, потому что элемент, выбранный по ID, не имеет потомков с этим классом.


Поскольку вы отображаете HTML-комментарии в разметке, я также хотел бы знать, есть ли у вас другой элемент на странице с идентификатором "0-0". Посмотрите на это.


Если ваши узлы фактически закомментированы, вам сначала нужно выбрать комментарий и заменить его разметкой, содержащейся внутри:

var container = document.getElementById('test1'),
    comment = container.firstChild;

while( comment && comment.nodeType !== 8 ) {
    comment = comment.nextSibling;
}

if( comment ) {
    container.innerHTML = comment.nodeValue;
}

... в результате:

<div class="testA" id="test1">
    <div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>
</div>

... но опять же, это маловероятно, поскольку ваш getElementsById работает.

0 голосов
/ 01 октября 2011

Вот способ сделать это для Firefox, Opera, Chrome и Safari. По сути, вы просто делаете div.innerHTML = div.innerHTML, чтобы интерпретировать его содержимое как HTML, и этот атрибут класса из файла XML будет обрабатываться как имя класса HTML.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title></title>
        <script>
            window.addEventListener("DOMContentLoaded", function() {
                var div = document.getElementsByTagName("div")[0];
                var req = new XMLHttpRequest();
                req.onreadystatechange = function() {
                    if (this.readyState === 4 && this.status === 200) {
                        var doc = this.responseXML;
                        div.appendChild(document.importNode(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0], true));
                        div.innerHTML = div.innerHTML;
                        alert(document.getElementsByClassName("colorSelector").length);
                    }
                };
                req.open("GET", "div.xml");
                req.send();
            }, false);
        </script>
    </head>
    <body>
        <div class="testA"></div>
    </body>
</html>

Удалите this.status === 200, если вы проводите локальное тестирование в браузерах, которые локально поддерживают xhr.

Функция importNode () не работает в IE (например, 9). Я получаю смутную ошибку "интерфейс не поддерживается".

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

var doc = this.responseXML;
var markup = (new XMLSerializer()).serializeToString(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0]);
div.innerHTML = markup;

, если разметка является дружественной к HTML, когда речь идет о конечных тегах для пустых элементов.

0 голосов
/ 30 сентября 2011

Теперь я добавляю первый div

Как вы это делаете?В responseXML есть элементы XML, а не элементы HTML.

  • Вы не сможете appendChild превратить их в HTML-документ не-XHTML;

  • на самом деле вы вообще не сможете appendChild добавить их в другой документ, вы должны использовать importNode для передачи элементов из одного документа в другой, в противном случае вы должны получитьWRONG_DOCUMENT_ERR;

  • , даже если вам удалось вставить их в HTML из-за слабости браузера, они по-прежнему являются элементами XML и не являются семантически элементами HTML.Следовательно, в атрибутах class нет ничего особенного;просто наличие этого имени не делает атрибут фактически представляющим класс.getElementsByClassName не будет возвращать элементы только потому, что они имеют атрибуты с name class;они должны быть элементами, определение языка которых связывает атрибуты с понятием классности (которое обычно означает HTML, XHTML или SVG).

(То же самое должно быть верно для id Атрибуты; просто наличие атрибута с именем id не делает его концептуально ID. Поэтому getElementById не должен работать. Существует способ связать произвольные атрибуты XML с ID-ness, который вы не 'Добиться классности, используя объявление <!ATTLIST в типе документа. Хотя обычно это не стоит беспокоить. Кроме того, xml:id является особым случаем, в реализациях, которые поддерживают XML ID.)

Вы можетепотенциально заставить его работать, если вы использовали страницу нативного XHTML, поместив в контент подходящие атрибуты xmlns, чтобы сделать его действительным-XHTML, а не просто произвольным XML, а затем используя importNode.Но в целом это того не стоит;как правило, проще возвращать строки разметки HTML (обычно в формате JSON) или необработанные данные XML, из которых сценарий на стороне клиента может сам создавать элементы HTML.

0 голосов
/ 30 сентября 2011

Пожалуйста, опишите, что вы делаете с возвращенными результатами. Существует значительная разница между nodeList и узлом, nodeLists: LIVE .

Таким образом, если вы назначите переменную nodeList, возвращаемую getElementsByClassName() (или аналогичной ей) переменной, эта переменная изменится, когда вы удалите узлы внутри nodeList из DOM.

0 голосов
/ 30 сентября 2011
<!--<div class="colorSelector" id="0-0">
        <div class="gbSelector" id="1-0">
            <table style="none" id="2-0"></table>
        </div>
    </div>-->

Приведенный выше код является серым по причине: это комментарий. Комментарии вообще не анализируются браузером и никак не влияют на страницу.

Вам придется проанализировать HTML-код, прочитать комментарии и создать новый DOM-объект с содержимым комментария.

...