Подтвердить что ты не робот

Как сравнить два элемента HTML

Как мы можем сравнить два элемента HTML, являются ли они идентичными или нет?

Я пробовал эту вещь, но не повезло

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

И затем при нажатии кнопки я вызываю функцию check()

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

Но это не работает. Все одинаково в двух div. Помимо этого Как мы можем сравнить, полностью ли идентичны два элемента HTML или нет. Включая их innerHTML, className, Id и их атрибуты.

Это выполнимо?

На самом деле, у меня есть два документа HTML, и я хочу удалить одинаковый контент из обоих. Так что два элемента могут иметь одинаковый идентификатор.

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

4b9b3361

Ответ 1

Обновить

См. Keen answer, а также ccproj ответ на тесно связанный вопрос. Для этого isEqualNode, но он сравнивает атрибуты class и style как текст, поэтому один и тот же набор классов или один и тот же набор свойств стиля в разных порядках заставит его думать, что узлы не эквивалентны. Ответ ccprog справляется с этим.

Оригинальный ответ

(См. Ниже полное, в значительной степени непроверенное и, конечно же, не подвергнутое рефакторингу решение "без подзарядки". Но сначала о кусочках.)

Сравнивать их innerHTML легко:

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

... хотя вы должны спросить себя, эквивалентны ли эти два элемента по вашим критериям:

<div><span class="foo" data-x="bar">x</span></div>
<div><span data-x="bar" class="foo">x</span></div>

... потому что их innerHTML будет другим (по крайней мере, в Chrome, и я подозреваю, что в большинстве, если не во всех браузерах). (Подробнее об этом ниже.)

Тогда вам нужно сравнить все их атрибуты. Насколько я знаю, jQuery не дает вам средства перечисления атрибутов, но DOM делает:

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;
}

затем

var names = [getAttributeNames(div[0]), getAttributeNames(div[1])];
if (names[0].length === names[1].length) {
    // Same number, loop through and compare names and values
    ...
}

Обратите внимание, что сортируя массивы выше, я предполагаю, что порядок их атрибутов не имеет значения в вашем определении "эквивалент". Я надеюсь, что это так, потому что, похоже, он не сохранился, так как я получаю разные результаты из разных браузеров при запуске этого теста. В этом случае мы должны вернуться к вопросу о innerHTML, потому что, если порядок атрибутов на самих элементах незначителен, то, вероятно, порядок атрибутов на дочерних элементах не должен быть значимым. Если это так, вам понадобится рекурсивная функция, которая проверяет потомков в соответствии с вашим определением эквивалента и не использует innerHTML вообще.

Затем возникает вопрос, связанный с этим последующим вопросом: что, если элементы имеют разные, но эквивалентные атрибуты style? Например:

<div id="a" style="color: red; font-size: 28px">TEST A</div>
<div id="b" style="font-size: 28px; color: red">TEST B</div>

Мой ответ там обращается к нему, просматривая содержимое объектов style элементов, например так:

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

К сожалению, как я говорю в этом ответе:

Обратите внимание, что приведенное выше не выполнится, если (один из них имеет color: red а другой - color: #ff0000), по крайней мере, в некоторых браузерах, потому что, когда свойство стиля использует строковое значение, обычно вы получаете значение таким, каким оно было поставляется, не нормируется. Вы можете использовать getComputedStyle, чтобы получить вычисленное значение (МОГ) вместо этого, но тогда мы попадаем в вопросах вокруг CSS применения: Два элемента с точно такой же разметки может иметь различные значения из getComputedStyle из - за того, где они находятся в DOM и CSS применяется к их в результате. И getComputedStyle не работает на узлах, которых нет в документе, поэтому вы не можете просто клонировать узлы, чтобы устранить эту проблему.

Но вы должны быть в состоянии собрать что-то вместе из приведенных выше фрагментов, чтобы сравнить два элемента в соответствии с вашими критериями.

Больше для изучения:


Вопрос странно интересовал меня, поэтому я немного подумала над ним и пришла к следующему. Он в основном не проверен, может использовать некоторый рефакторинг и т.д., Но он должен помочь вам в этом. Я, опять же, предполагаю, что порядок атрибутов не имеет значения. Ниже предполагается, что даже малейшая разница в тексте значительна.

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;
}

Живые примеры:

Ответ 2

Вы можете использовать:

element1.isEqualNode(element2);

В вашем конкретном примере:

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

DOM Level 3 Core Spec содержит все подробности. По сути, это возвращает true для двух узлов, имеющих соответствующие атрибуты, потомки и атрибуты потомков.

Там аналогичный .isSameNode(), который возвращает true, только если оба элемента одинаковы node. В вашем примере это не те же узлы, но они равны узлам.

Ответ 3

Почему бы не сделать это легко?

<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/

Ответ 4

Как это кодируется?

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) ?