I'm managing a list of names in Javascript. When you check a box, your name appears in the list. When you uncheck it, it gets crossed out. And when you set the box to the indeterminate state, your name's removed.
I've got the name of the currently logged in user in a hidden div. The name is a span with style attributes.
I check if the name is already in the list with isEqualNode. When it's in the list when the page loads, it works fine: the name is found and so is updated when the box checked state change.
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's name in the list
When the name is not in the list, I clone the span.
var newName = document.getElementById('curUser').firstChild.cloneNode(true);
bullet.appendChild(newName);
This works, visually.
But I stumbled on something tricky: newName.isEqualNode(document.getElementById('curUser').firstChild)
is false! So if the box state change again, the newly added name won't be found and a new one will be created, again.
Here is what the span looks like:
<span style="font-weight: bold ; color: #003380 ;">Pikrass</span>
For the moment I'll just make the check less strict (I can just check the text data inside the span instead of relying on isEqualNode), but I'm interested in why a cloned node can be different than the original one, according to isEqualNode.
Relevant specs : cloneNode, isEqualNode
EDIT: I tested with Firefox and Chromium. With Firefox isEqualNode returns false, but with Chromium it returns true. Thanks Felix for pointing this out.
Just figured this out. According to specification, isEqualNode returns true only if both elements have equal amount of attributes. But if the source element has an ID, it is not copied since IDs shoud be unique, so it has less attributes. With class instead of ID it works fine.
Markup:
<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/
It is written here Mozilla's reference (thanks @Bergi)
The duplicate node returned by cloneNode() receives a new uniqueID when it is added to another node
As you are doing an append, the id is probably changed at this moment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With