Cloned node не равен оригиналу node (с isEqualNode)

Я управляю списком имен в Javascript. Когда вы установите флажок, ваше имя появится в списке. Когда вы снимете его, его вычеркивают. И когда вы установите поле в неопределенное состояние, ваше имя удалено.

У меня есть имя текущего пользователя в скрытом div. Имя - это диапазон с атрибутами стиля.

Я проверяю, есть ли имя в списке с isEqualNode. Когда он находится в списке при загрузке страницы, он отлично работает: имя найдено и поэтому обновляется, когда в поле отмечено состояние изменения.

for(var i=0 ; i < bullet.childNodes.length ; i++) {
    var node = bullet.childNodes[i];
    if(node.className == 'crossed')
        node = node.firstChild;
    if(node.isEqualNode(document.getElementById('curUser').firstChild))
        break;
}
// if i < bullet.childNodes.length, then we found the user name in the list

Когда имя отсутствует в списке, я клонирую диапазон.

var newName = document.getElementById('curUser').firstChild.cloneNode(true);
bullet.appendChild(newName);

Это работает визуально.

Но я наткнулся на что-то сложное: newName.isEqualNode(document.getElementById('curUser').firstChild) ложно! Поэтому, если состояние окна снова изменится, новое добавленное имя не будет найдено, и новый будет создан снова.

Вот как выглядит этот диапазон:

<span style="font-weight: bold ; color: #003380 ;">Pikrass</span>

На данный момент я просто сделаю проверку менее строгой (я могу просто проверить текстовые данные внутри диапазона вместо того, чтобы полагаться на isEqualNode), но меня интересует, почему клонированный node может отличаться от оригинальный, согласно isEqualNode.

Соответствующие спецификации: cloneNode, isEqualNode


EDIT: Я тестировал с Firefox и Chromium. С Firefox isEqualNode возвращает false, но с Chromium он возвращает true. Спасибо Феликс за это.

Ответ 1

Лучше поздно, чем никогда.:)

Я больше не могу воспроизвести проблему с Firefox 17, так, как обсуждалось в комментариях, это, вероятно, было ошибкой в ​​Gecko, которая была исправлена.

Однако я не смог найти отчет об ошибке. Я отмечу этот ответ как принято на данный момент, но если кто-то может найти отчет об ошибке или объяснение того, что происходит под капотами, я соглашусь с этим.

Комментарии Берги подходят для двух других ответов.

Ответ 2

Просто понял это. Согласно спецификация, isEqualNode возвращает true, только если оба элемента имеют одинаковое количество атрибутов. Но если исходный элемент имеет идентификатор, он не копируется, поскольку идентификаторы являются уникальными, поэтому у него меньше атрибутов. С классом вместо ID он отлично работает.

Разметка:

<div id="withId">withId content</div>
<div class="withoutId">withoutId content</div>

JS:

function test(node) {
    var copy = node.clone(true);
    document.body.appendChild(copy);
    console.log('are equal: ' + copy.isEqualNode(node)
        + ', attributes lengths: ' + node.attributes.length + ' ' + copy.attributes.length
        + ', ids: ' + node.getAttribute('id') + ' ' + copy.getAttribute('id'));
}

test(document.getElementById('withId'));
// are equal: false, attributes lengths: 1 0, ids: withId null

test(document.getElementsByClassName('withoutId')[0]);
// are equal: true, attributes lengths: 1 1, ids: null null

http://jsfiddle.net/igorz/fxtDw/

Ответ 3

Здесь написано ссылка на Mozilla (спасибо @Bergi)

Дубликат node, возвращаемый cloneNode(), получает новый уникальный идентификатор, когда он добавляется в другой node

Как вы делаете append, идентификатор, вероятно, будет изменен в данный момент.