How to compare two HTML elements

How can we compare two HTML elements, are they identical or not?

I tried this thing but no luck

<div class="a"> Hi this is sachin tendulkar </div> <div class="a"> Hi this is sachin tendulkar </div> 

And then when I click the button, I call the check () function

 var divs = $(".a"); alert(divs.length); // Shows 2 here which is correct if (divs.get(0) == divs.get(1)) alert("Same"); 

But that does not work. Everything is the same in two divs. Beyond this, How can we compare whether two HTML elements are completely identical or not. Including their innerHTML, className, Id and their attributes.

Is this doable?

In fact, I have two HTML documents and I want to remove the same content from both. So two elements can have the same identifier.

PS: Update after Crowder's valuable comments. If we compare two elements as strings, we wonโ€™t get a match, as their order of attributes can change. The only option is to iterate over each child attribute and match. I still have to find a fully operational implementation strategy.

+23
javascript jquery html
May 21 '12 at 5:10
source share
4 answers

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) // or if you prefer using jQuery if (divs.html() === $(divs[1]).html()) // The first one will just be the HTML from div 0 

... 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]) { // Not equivalent, stop } } // Equivalent 

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:

+28
May 21 '12 at 5:16
source share

You can use:

 element1.isEqualNode(element2); 

In your specific example:

 var divs = $(".a"); if ( divs.get(0).isEqualNode(divs.get(1)) ) alert("Same"); 

DOM Level 3 Core Spec contains all the details. Essentially, this returns true for two nodes that have the appropriate attributes, descendants, and descendant attributes.

There is a similar .isSameNode (), which returns true only if both elements are the same node. In your example, these are not the same nodes, but they are equal to the nodes.

+42
Oct 13 '13 at 6:37 on
source share

Why not make it easy?

 <div id="div1"><div class="a"> Hi this is sachin tendulkar </div></div> <div id="div2"><div class="a"> Hi this is sachin tendulkar </div></div> if($('#div1').html() == $('#div2').html()) alert('div1 & div2 are the same'); else alert('div1 & div2 are different'); 

http://jsfiddle.net/5Zwy8/1/

+1
May 21 '12 at 5:21
source share

How is this encoded?

 var d1 = document.createElement("div"); d1.appendChild(divs.get(0)); var d2 = document.createElement("div"); d2.appendChild(divs.get(1)); if (d1.innerHTML == d2.innerHTML) ? 
0
May 21 '12 at 5:22 a.m.
source share



All Articles