I thought I wanted to compare the DOM trees for a couple of nodes. I ended up putting this together:
function normalizeString(s) {
return s.replaceAll(/\s+/g, ' ').trim();
}
function compareAttributes(a1, a2) {
a1 = a1 || [];
a2 = a2 || [];
let tested = {};
for (const attr of a1) {
tested[attr.name] = true;
if (attr.value !== a2[attr.name].value) {
return `${attr.name}: ${attr.value} !== ${a2[attr.name].value}`;
}
}
for (const attr of a2) {
if (tested[attr.name]) {
continue;
}
if (attr.value !== a1[attr.name].value) {
return `${attr.name}: ${a1[attr.name].value} !== ${attr.value}`;
}
}
return '';
}
function compareNodes(n1, n2, path) {
if (n1.isEqualNode(n2)) {
return '';
}
if (n1.nodeType !== n2.nodeType) {
return `${path} noteType: ${n1.nodeType} !== ${n2.nodeType}`;
}
if (n1.nodeType === Node.TEXT_NODE) {
const t1 = normalizeString(n1.textContent);
const t2 = normalizeString(n2.textContent);
if (t1 !== t2) {
return `${path} text: <<${t1}>> !== <<${t2}>>`;
}
}
if (n1.tagName !== n2.tagName) {
return `${path} tag: ${n1.tagName} !== ${n2.tagName}`;
}
if (n1.className !== n2.className) {
return `${path} class: ${n1.className} !== ${n2.className}`;
}
const attrDiff = compareAttributes(n1.attributes, n2.attributes);
if (attrDiff) {
return `${path} ${attrDiff}`;
}
if (n1.childNodes.length !== n2.childNodes.length) {
return `${path} childNodes.length: ${n1.childNodes.length} !== ${n2.childNodes.length}`;
}
for (let i = 0; i < n1.childNodes.length; i++) {
let result = compareNodes(n1.childNodes[i], n2.childNodes[i], `${path}<${n1.tagName}>.childNodes[${i}]`);
if (result) {
return result;
}
}
return '';
}
How would you have done it? (I’d be unsurprised if this has some bugs.)
After writing this though, I realized that comparing the HTML from n1.getHTML()
vs n2.getHTML()
was better for my purposes. (I don’t remember using getHTML() before; from that MDN link, it sounds like as I’m using it here, it’s equivalent to innerHTML.)
By the way, here’s what Gemini came up with in a few seconds in response to the prompt “could you write javascript to compare two dom nodes for equality?”
function compareDOMNodes(node1, node2) {
// Check if nodes are the same element type
if (node1.nodeName !== node2.nodeName) {
return false;
}
// Check if attributes are equal
if (node1.attributes.length !== node2.attributes.length) {
return false;
}
for (let i = 0; i < node1.attributes.length; i++) {
const attr1 = node1.attributes[i];
const attr2 = node2.attributes[i];
if (attr1.nodeName !== attr2.nodeName || attr1.nodeValue !== attr2.nodeValue) {
return false;
}
}
// Check if child nodes are equal
if (node1.childNodes.length !== node2.childNodes.length) {
return false;
}
for (let i = 0; i < node1.childNodes.length; i++) {
if (!compareDOMNodes(node1.childNodes[i], node2.childNodes[i])) {
return false;
}
}
// Nodes are equal
return true;
}
I like mine a bit better, but to be fair to Gemini, I also didn’t play with the prompt to refine it.
Leave a Reply