如何从上一个元素的NodeList中获取所有类名?

时间:2019-05-27 06:52:04

标签: javascript css dom classname

我想向放置在某个元素块后面的每个按钮添加一些事件侦听器。如果单击此按钮,将返回上一个元素块中的所有元素类。

我在这里https://gist.github.com/cssence/41c8279810b1db71670d.js

找到了从NodeList获取类的脚本
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 :(得分:0)

要获取上一个元素,请使用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>