遍历DOM,获取出现次数最多的文本,并向父级添加一个class

Traversing the DOM, getting text with highest appearance and add a class to the parent

我正在遍历这个DOM:

     <ul>
        <li class="item">
           <span class="category">
              most occurring text
           </span>
        </li>
        <li class="item">
           <span class="category">
              some text
           </span>
        </li>
        <li class="item">
           <span class="category">
              some text
           </span>
        </li>
        <li class="item">
           <span class="category">
              most occurring text
           </span>
        </li>
        <li class="item">
           <span class="category">
              most occurring text
           </span>
        </li>
     </ul>

使用以下代码:

var myNodelist = Array.from(document.querySelectorAll(".category"));
var obj = {};

for(var i = 0; i < myNodelist.length; i++){
    //convert array to object with unique elements and number of times 
    each element is repeated
    var x = myNodelist[i].innerHTML;
    //console.log(x);

    if(!obj[x]){
       obj[x] = 1;
    } else {
       obj[x]++;
    }
 }

 var index = 0;
 var max = 0;

 for(var obIndex in obj) {
    // Traverse the object to get the element
    if(obj[obIndex] > max) {
       max = obj[obIndex];
       index = obIndex.replace(" ", "");
    }
 }

 console.log(index + " is max time repeated: " + max + " times." );

 var v = document.getElementsByClassName("category");

 for(var m = 0; m < myNodelist.length; m++) {
     var subText = myNodelist[m].childNodes;
     var len = subText.length;

     for (var jj = 0; jj < len; jj++) {
        if(subText[jj].nodeType === Node.TEXT_NODE) {
             console.log(subText[jj].nodeValue);
             subText[jj].nodeValue = 
             subText[jj].nodeValue.replace(/Mock/,"123");
        }
     }
 }

目前,我正在使用 DOM 中最高文本出现率的值成功获取索引。然后我再次遍历 Nodelist,评估它是否是 a,

Node.TEXT_NODE

https://developer.mozilla.org/de/docs/Web/API/Node/nodeType

现在我只知道怎么替换

textNode.value

用另一个值。 我真正想要实现的是获取 textNode 的 parentNode 并向其添加 class 。如果满足索引条件(最高外观)。我发现的是

Adding a class to a given element.ParentNode MDN

问题是我真的不知道该怎么做 从 second for loop 访问 parentNode 并添加一个 class 到 parentNode,所以只有索引(文本)的所有父节点(span 标签) 值)得到某个class.

感谢帮助!

What i am really trying to achieve is to get the parentNode of the textNode and add a class to it.

你不需要找到它,你已经有 myNodelist[m] 你正在迭代的子节点。

If the condition for index (highest appearance) is met.

您在这里 node-Value subText[jj].nodeValue,并且您已经拥有 obj 出现次数 [=14] =]

所以,只需添加这个逻辑

if ( obj[ subText[jj].nodeValue ] == max )
{
  //logic to add the class should be here
  myNodelist[m].classList.add("otherclass");
}
subText[jj].nodeValue = subText[jj].nodeValue.replace(/Mock/,"123");

您可以在 myNodelist[m]

上使用 parentNode 访问 li

var myNodelist = Array.from(document.querySelectorAll(".category"));
var obj = {};

for(var i = 0; i < myNodelist.length; i++){
    //convert array to object with unique elements and number of times 
    //each element is repeated
    var x = myNodelist[i].innerHTML;
    //console.log(x);

    if(!obj[x]){
       obj[x] = 1;
    } else {
       obj[x]++;
    }
 }

 var index = 0;
 var max = 0;

 for(var obIndex in obj) {
    // Traverse the object to get the element
    if(obj[obIndex] > max) {
       max = obj[obIndex];
       index = obIndex.replace(" ", "");
    }
 }

 console.log(index + " is max time repeated: " + max + " times." );

 var v = document.getElementsByClassName("category");

 for(var m = 0; m < myNodelist.length; m++) {
     var subText = myNodelist[m].childNodes;
     var len = subText.length;

     for (var jj = 0; jj < len; jj++) {
        if(subText[jj].nodeType === Node.TEXT_NODE) {
           if (obj[subText[jj].nodeValue] == max) {
              myNodelist[m].parentNode.className += " red";
           }
           console.log(subText[jj].nodeValue);
           subText[jj].nodeValue = 
           subText[jj].nodeValue.replace(/Mock/,"123");
        }
     }
 }
.red {
  color: red;
}
<ul>
    <li class="item">
       <span class="category">
          most occurring text
       </span>
    </li>
    <li class="item">
       <span class="category">
          some text
       </span>
    </li>
    <li class="item">
       <span class="category">
          some text
       </span>
    </li>
    <li class="item">
       <span class="category">
          most occurring text
       </span>
    </li>
    <li class="item">
       <span class="category">
          most occurring text
       </span>
    </li>
 </ul>

要获取文本节点的父节点,只需使用 myTextNode.parentNode,然后使用 classList 将 class 添加到父节点。这也可以使用 treewalker api.

来实现

function markMostOccurring(parentSelector, markFn) {
  var parent = document.querySelector(parentSelector) || document.body;
  var walker = document.createTreeWalker(parent, NodeFilter.SHOW_TEXT, { 
    acceptNode: node => !!node.nodeValue.trim()
  });
  
  var occurenceMap = {};
  while(walker.nextNode()) {
    var key = walker.currentNode.nodeValue.trim();
    var nodes = occurenceMap[key] = occurenceMap[key] || [];
    nodes.push(walker.currentNode);
  }
  
  var nodes = Object.keys(occurenceMap)
    .sort((a, b) => occurenceMap[b].length - occurenceMap[a].length)
    .map(key => occurenceMap[key])[0]
    .forEach(node => markFn.call(node));
}

markMostOccurring('.container', function() {
  this.parentNode.classList.add('mark');
  this.nodeValue = this.nodeValue.replace('most', 'cat'); 
});
.mark {
  color: red;
}
<ul class="container">
  <li class="item">
    <span class="category">
        most occurring text
    </span>
  </li>
  <li class="item">
    <span class="category">
      some text
    </span>
  </li>
  <li class="item">
    <span class="category">
      some text
    </span>
  </li>
  <li class="item">
    <span class="category">
      most occurring text
    </span>
  </li>
  <li class="item">
    <span class="category">
      most occurring text
    </span>
  </li>
</ul>