Как получить все имя класса из NodeList предыдущего элемента? - PullRequest
0 голосов
/ 27 мая 2019

Я хочу добавить прослушиватель событий для каждой кнопки, расположенной после некоторого блока элемента.Эта кнопка предназначена для возврата всех классов элементов из предыдущего блока элемента при нажатии.

Я нашел скрипт для получения классов из NodeList здесь, https://gist.github.com/cssence/41c8279810b1db71670d.js

for (var k = 0; k < trigger.length; k++) {
  trigger[k].addEventListener('click', function(e) {
    nav.classList.toggle('hidden');
    (function listAllUsedClassNames() {
      var classNames = {};
      Array.prototype.forEach.call(this.previousElementSibling.querySelectorAll("*"), function(element) {
        if (typeof element.className === "string") {
          element.className.split(" ").forEach(function(className) {
            if (className) {
              classNames[className] = true;
            }
          });
        };
      });
      return Object.keys(classNames);
    }());
  }, false);
}

Я хочу, чтобы какой-то массив содержалвсе классы предыдущего блока возвращаются после нажатия кнопки.Было бы лучше, если бы результат был уникальным и не содержал дублирующихся элементов.

1 Ответ

0 голосов
/ 27 мая 2019

Чтобы получить предыдущий элемент, используйте previousElementSibling.Выполните итерацию по childNodes, чтобы получить классы элемента, используя classList.

let classes = [];
document.querySelectorAll('button')
  .forEach(button => {
    button.addEventListener('click', function() {
      classes = [];
      const prev = this.previousElementSibling;
      classes.push(...prev.classList);
      prev.childNodes.forEach(child => {
        if(child.nodeType == 3) return; // Ignore text node
        classes.push(...child.classList);
      })
      console.log(classes);
    });
  });
<div class="first">
  <p class="childOfFirst">Lorem ipsum dolor sit amet consectetur, adipisicing elit. Repudiandae totam dicta libero vero dolore aperiam consectetur. Non veritatis quo praesentium!</p>
</div>
<button>Button1</button>
<div class="second">
  <p class="childOfSecond">Lorem ipsum dolor sit amet consectetur adipisicing elit. Aspernatur, hic.</p>
</div>
<button>Button2</button>

Для множественного вложения используйте recursion

let classes = [];

document.querySelectorAll('button')
    .forEach(button => {
        button.addEventListener('click', function() {
            classes = [];
            const prev = this.previousElementSibling;
            if(prev.children.length > 0) {
                const output = getNestedClasses([...prev.children]);
                classes.push(...prev.classList, ...output);
                console.log('With Duplicates', classes);
                const uniqueClassList = removeDuplicateClasses(classes)
                console.log('Without Duplicates', uniqueClassList);
            }
        });
    });

function getNestedClasses(childrens) {
    return childrens.reduce((accu, ele) => {
        if(ele.children.length > 0) {
            accu.push(...ele.classList);
            return accu.concat(getNestedClasses([...ele.children]));
        } else {
            return accu.concat([...ele.classList]);
        }
    }, []);
}

function removeDuplicateClasses(classArr) {
    return Object.keys(classArr.reduce((accu, name) => {
        accu[name] += (accu[name] || 0);
        return accu;
    }, {}));
}
<div class="first">
    <p class="firstChild">First Child
        <span class="firstGrandChild">First Grand Child</span>
        <span class="secondGrandChild">Second Grand Child</span>
    </p>    
    <p class="secondChild duplicate">Second Child</p>
    <p class="duplicate"></p>
    <p class="thirdChild">Third Child</p>
</div>
<button>Button1</button>
...