Подсчет вложенных тегов

241
07 июня 2021, 10:50

Не могу разобраться почему не считает, вроде отладчиком прошелся посмотреть чему равен li.dataset.liCount в процессе выполнения, и там почему-то NaN

for (let li of document.documentElement.getElementsByTagName('li')) {
      li.dataset.liCount = 0; // прописываем изначально всем li кастомный атрибут data-li-count равный 0, чтобы потом увеличение ++ правильно работало в плане типов данных
      countChild(li);
      console.log (li.firstChild.data.trim()); // выводим текстовое содержимое li
      console.log (li.dataset.liCount); // выводим количество вложенных li
    }

    function countChild (li) {
      if (li.firstElementChild) { // проверка есть ли дети элементы
        for (let child of li.children) { // если есть, то проверяем среди детей элементов, кто LI
          if (child.tagName === 'LI') {
            li.dataset.liCount++; // увеличиваем кастомный атрибут data-li-count
          }
          countChild (child); // запускаем функцию заново для ребенка li
       }
      }
    }
Answer 1

Эмм... это одна строчка:

let list = document.querySelectorAll('li'); 
 
for( let li of list ){ 
  li.dataset.liCount = li.querySelectorAll('li').length; 
   
  li.insertAdjacentHTML('afterbegin', 'Вложено li: ' + li.dataset.liCount); // для демо 
}
<ul> 
  <li> 
    <ul> 
      <li></li> 
      <li></li> 
      <li> 
        <ul> 
          <li></li> 
          <li></li> 
          <li></li> 
        </ul> 
      </li> 
    </ul> 
  </li> 
  <li></li> 
</ul>

А в вашем коде, сложно сказать, где конкретно ошибка - местами есть косяки и он просто не работает (например, если в процессе найдется child-UL, то ему тоже запишется dataset). Попробовал написать рабочий вариант, максимально похожий на ваш)) Понадобилась внешняя переменная (т.к. функция вызывает сама себя), чтобы не запутавшись, спокойно плюсовать ему +1 после каждого найденного li. И в самом конце - записать это число в dataset.

let innerLi; 
for (let li of document.getElementsByTagName('li')) { 
  innerLi = 0; 
  li.dataset.liCount = countChild(li); 
 
  li.insertAdjacentHTML('afterbegin', 'Вложено li: ' + li.dataset.liCount); // для демо 
} 
 
function countChild(li) { 
  if (!li.children.length) { return innerLi; } 
  // Детей будет ноль - функция сразу прервется 
 
  for (let child of li.children) { 
    if (child.tagName === "LI") { 
      innerLi++; 
    } 
    countChild(child); 
  } 
  return innerLi; 
}
<ul> 
  <li> 
    <ul> 
      <li></li> 
      <li></li> 
      <li> 
        <ul> 
          <li></li> 
          <li></li> 
          <li></li> 
        </ul> 
      </li> 
    </ul> 
  </li> 
  <li></li> 
</ul>

Но работать с такими переменными будет не очень удобно, как только у вас код станет чуть длиннее. Поэтому есть более классный вариант (см. google - функции-конструкторы):

for (let li of document.getElementsByTagName('li')) { 
  li.dataset.liCount = ( new Count() ).child(li); 
   
  li.insertAdjacentHTML('afterbegin', 'Вложено li: ' + li.dataset.liCount); // для демо 
} 
 
function Count() {  
  // функция при вызове new - будет создавать объект. this будет ссылаться на этот объект 
  this.innerLi = 0; 
 
  this.child = function(li) { 
    if (!li.children.length) { return this.innerLi; } 
 
    for (let child of li.children) { 
      if (child.tagName === "LI") { 
        this.innerLi++; 
      } 
      this.child(child); 
    } 
    return this.innerLi; 
  } 
}
<ul> 
  <li> 
    <ul> 
      <li></li> 
      <li></li> 
      <li> 
        <ul> 
          <li></li> 
          <li></li> 
          <li></li> 
        </ul> 
      </li> 
    </ul> 
  </li> 
  <li></li> 
</ul>

READ ALSO
Не подключаются стили CSS в проекте на Django

Не подключаются стили CSS в проекте на Django

Всем добрый день! При разработке проекта на Django не удается подключить стили CSSСоздана директория static, где лежат как стили, так и картинки

185
Как сделать чтобы функция выполнялась только тогда, когда выполнились оба условия?

Как сделать чтобы функция выполнялась только тогда, когда выполнились оба условия?

Как сделать чтобы функция выполнялась только тогда, когда выполнились оба условия? Необходимо, чтобы блок становился серым только при условии,...

108
Передача данных на форму через DataBinding

Передача данных на форму через DataBinding

Есть 3 класса и под каждый из классов сделана привязка через DataBinding для передачи данных на форму, и 4й главный обобщающий куда занесены данные...

212
C# SOAP - прочитать полученный массив

C# SOAP - прочитать полученный массив

Пытаюсь тут работать с SOAP

120