Refresh
See Keen's answer, as well as ccproj's answer to a closely related question . For this, isEqualNode , but it compares the class and style attributes as text, so the same set of classes or the same set of style properties in different orders will make him think that the nodes are not equivalent. Ccprog's answer handles this.
Original answer
(See below for a complete, largely untested and, of course, refactored โno-chargeโ solution. But first, on the pieces.)
Comparing their innerHTML easy:
if (divs[0].innerHTML === divs[1].innerHTML)
... although you should ask yourself if these two elements are equivalent according to your criteria:
<div><span class="foo" data-x="bar">x</span></div> <div><span data-x="bar" class="foo">x</span></div>
... because their innerHTML will be different (at least in Chrome, and I suspect in most, if not all browsers). (More on this below.)
Then you need to compare all their attributes. As far as I know, jQuery does not give you a means of listing attributes, but the DOM does:
function getAttributeNames(node) { var index, rv, attrs; rv = []; attrs = node.attributes; for (index = 0; index < attrs.length; ++index) { rv.push(attrs[index].nodeName); } rv.sort(); return rv; }
then
var names = [getAttributeNames(div[0]), getAttributeNames(div[1])]; if (names[0].length === names[1].length) { // Same number, loop through and compare names and values ... }
Note that when sorting the arrays above, I assume that the order of their attributes does not matter in your equivalent definition. I hope this is because it does not seem to have survived, since I get different results from different browsers when I run this test . In this case, we should return to the question of innerHTML , because if the order of the attributes on the elements themselves is insignificant, then probably the order of the attributes on the children should not be significant. If so, you will need a recursive function that checks the children according to your equivalent definition and does not use innerHTML at all.
Then the question arises related to this subsequent question : what if the elements have different but equivalent style attributes? For example:
<div id="a" style="color: red; font-size: 28px">TEST A</div> <div id="b" style="font-size: 28px; color: red">TEST B</div>
My answer there addresses it, looking at the contents of the style objects of the elements, for example like this:
const astyle = div[0].style; const bstyle = div[1].style; const rexDigitsOnly = /^\d+$/; for (const key of Object.keys(astyle)) { if (!rexDigitsOnly.test(key) && astyle[key] !== bstyle[key]) {
Unfortunately, as I say in this answer:
Please note that the above will not work if (one of them has color: red and the other is color: #ff0000 ), at least in some browsers, because when the style property uses a string value, you usually get the value like this how it was delivered is not standardized. You can use getComputedStyle to get the computed value (MTF) instead, but then we get into questions about CSS application: Two elements with exactly the same markup can have different values โโfrom getComputedStyle because of where they are in the DOM and CSS applied to them as a result. And getComputedStyle does not work on nodes that are not in the document, so you cannot just clone nodes to fix this problem.
But you should be able to put something together from the above snippets in order to compare the two elements according to your criteria.
More to learn:
The question strangely interested me, so I thought about it a bit and came to the next. It is mostly untested, may use some refactoring, etc., but it should help you with that. I, again, assume that the order of the attributes does not matter. It is assumed below that even the slightest difference in the text is significant.
function getAttributeNames(node) { var index, rv, attrs; rv = []; attrs = node.attributes; for (index = 0; index < attrs.length; ++index) { rv.push(attrs[index].nodeName); } rv.sort(); return rv; } function equivElms(elm1, elm2) { var attrs1, attrs2, name, node1, node2; // Compare attributes without order sensitivity attrs1 = getAttributeNames(elm1); attrs2 = getAttributeNames(elm2); if (attrs1.join(",") !== attrs2.join(",")) { display("Found nodes with different sets of attributes; not equiv"); return false; } // ...and values // unless you want to compare DOM0 event handlers // (onclick="...") for (index = 0; index < attrs1.length; ++index) { name = attrs1[index]; if (elm1.getAttribute(name) !== elm2.getAttribute(name)) { display("Found nodes with mis-matched values for attribute '" + name + "'; not equiv"); return false; } } // Walk the children for (node1 = elm1.firstChild, node2 = elm2.firstChild; node1 && node2; node1 = node1.nextSibling, node2 = node2.nextSibling) { if (node1.nodeType !== node2.nodeType) { display("Found nodes of different types; not equiv"); return false; } if (node1.nodeType === 1) { // Element if (!equivElms(node1, node2)) { return false; } } else if (node1.nodeValue !== node2.nodeValue) { display("Found nodes with mis-matched nodeValues; not equiv"); return false; } } if (node1 || node2) { // One of the elements had more nodes than the other display("Found more children of one element than the other; not equivalent"); return false; } // Seem the same return true; }
Live examples: