Переопределение getElementsByClassName с нуля (только Vanilla JS)

Чтобы лучше познакомиться с DOM и рекурсией, я решил воссоздать getElementsByClassName с нуля (только для JS Vanilla, без jQuery). В настоящее время я могу найти все элементы в DOM, которые имеют класс, который я хочу, но у меня возникают проблемы с тем, чтобы найти способ получить только элементы, которые имеют два определенных класса (или больше).

<div class="one two">
   <h1 class="one">
      <span class="one two">
  </h1>
</div>

Моя текущая реализация возвращает то, что я ожидаю, каждый элемент, который содержит класс 'one', возвращается:

getElementsByClassName('one');
[<div class="one two"></div>, <h1 class="one"></h1>, <span class="one two"</span>]

К чему я пытаюсь добраться:

getElementsByClassName('one two');
[<div class="one two"></div>, <span class="one two"</span>]

Одна из проблем, с которыми я столкнулся, связана с classList.contains:

element.classList;
// ['one, 'two'];

element.classList.contain("one");
//returns true since the value actually exists


//PROBLEM:
element.classList.contains("one two"); 
//this is looking for "one two" in the array  and not 'one' and 'two'.
//this returns false & my code breaks  

//How would I be able to do something like this, even if it
//means recreating my own helper contains function?
contains('one','two');

Моя функция:

var getElementsByClassName = function(className){
   var results = [];
   function getClass(nodeList){
     var childList = nodeList.children;
     _forEach(childList, function(node) {
     //1st level body check
      if(node.classList  && node.classList.contains(className)){
        results.push(node);
      }

      //has children, recurse
      if(node.children) {
        getClass(node);
      }
      else {
        getClass(node);
      }
    });
   }
   getClass(document.body);
   return results;
}



//Helper forEach function to iterate over array like DOM objects
var _forEach = function(collection, func) {
 for(var i = 0; i < collection.length; i++) {
   func(collection[i], i, collection);
 }
}

1 ответ

Решение

Комментарии в коде - я не реализовал это для вас, просто указал, что вы будете делать:

var getElementsByClassName = function(className){
   // ***Here, split className on whitespace into an array **
   var results = [];
   function getClass(nodeList){
     var childList = nodeList.children;
     _forEach(childList, function(node) {
     //1st level body check
      // **Here, only include the element if Array#every is true,
      // **where you give Array#every a function that does your
      // classList.contains on the name for that iteration
      if(node.classList  && node.classList.contains(className)){
        results.push(node);
      }

      //has children, recurse
      if(node.children) {
        getClass(node);
      }
      else {
        getClass(node);
      }
    });
   }
   getClass(document.body);
   return results;
}
Другие вопросы по тегам