Vanilla JS:如何获取具有某个类的父元素的索引?

时间:2017-05-15 22:32:25

标签: javascript arrays for-loop

简而言之

点击给定HTML下面的链接,我需要获取具有“analytics”类的父级索引。例如,单击链接“myID2 Link 1”将返回1.

<ul id="myID1" class="analytics" data-attribute="hpg:shocking">
  <li><a href="http://myurl.com/">myID1 Link 1</a></li>
  <li><a href="http://myurl.com/">myID1 Link 2</a></li>
  <li><a href="http://myurl.com/">myID1 Link 3</a></li>
</ul>
<ul id="myID2" class="analytics" data-attribute="hpg:expected">
  <li><a href="http://myurl.com/">myID2 Link 1</a></li>
  <li><a href="http://myurl.com/">myID2 Link 2</a></li>
  <li><a href="http://myurl.com/">myID2 Link 3</a></li>
</ul>
<ul id="myID3" class="analytics" data-attribute="hpg:unexpected">
  <li><a href="http://myurl.com/">myID3 Link 1</a></li>
  <li><a href="http://myurl.com/">myID3 Link 2</a></li>
  <li><a href="http://myurl.com/">myID3 Link 3</a></li>
</ul>

我尝试了什么

我目前正在使用两个单独的循环,一个用于迭代父项,另一个用于向链接添加单击事件。

// helper function to check parent for a class
function hasParentWithClass(element, classname) {
  if (element.className.split(' ').indexOf(classname) >= 0) {
    return true;
  }
  return element.parentNode && hasParentWithClass(element.parentNode, classname);
}

// get all elements with class "analytics"
var analytics = document.querySelectorAll('.analytics');
var containerClass = [];

for (var z = 0; z < analytics.length; z++) {
  var inc = z + 1;
  containerClass.push(analytics[z].getAttribute('id'));
}

var links = analytics.getElementsByTagName('a');

for (var i = 0; i < links.length; i++) {
  links[i].addEventListener('click', function(e) {
    e.preventDefault();

    if (hasParentWithClass(this, 'analytics')) {
    // output index of parent
    } else {
    // do nothing
    }
  }, false);
}

问题

我正在努力使用第二个循环中第一个循环的逻辑。具体来说,从第二个for循环中搜索var containerClass以获取父级的索引,因为它存储在var containerClass中。 .indexOf对我不好。

实现这一目标的最直接,最有效的方法是什么?

2 个答案:

答案 0 :(得分:1)

这比你想象的要简单得多。如果我们将click事件处理程序分配给父元素,我们可以使用事件冒泡来解决问题。当您单击链接时,它不仅会触发您单击的链接的click事件,而且该事件也将通过该链接的祖先元素“冒泡”。如果我们在父级捕获事件,我们就可以得到它的索引。

另外,正如@Dave Thomas指出的那样,您的列表的HTML结构无效。

// Get all the .analytics elements
var analytics = document.querySelectorAll(".analytics");

// Loop through them
Array.prototype.slice.call(analytics).forEach(function(item, index, arry){

  // Set up click event handlers for each of the parents
  item.addEventListener("click", function(evt){
    // Just access the index of the parent within the group
    console.clear();
    console.log("The index of the parent is: " +  index)
    
    // Now, display the index of the link within its parent .analytics element
    
    // Get all the anchors in the current analytics container
    var anchors = Array.prototype.slice.call(item.querySelectorAll("a"));
    
    // Get the index of the anchor within the set of anchors
    var idx = Array.prototype.indexOf.call(anchors, evt.target);
    console.log("The index of the link within the parent is: " + idx);
  });
});
<div id="myID1" class="analytics" data-attribute="hpg:shocking">
  <ul>
    <li><a href="#">myID1 Link 1</a></li>
    <li><a href="#">myID1 Link 2</a></li>
    <li><a href="#">myID1 Link 3</a></li>
  </ul>
</div>
<div id="myID2" class="analytics" data-attribute="hpg:expected">
  <ul>
    <li><a href="#">myID2 Link 1</a></li>
    <li><a href="#">myID2 Link 2</a></li>
    <li><a href="#">myID2 Link 3</a></li>
  </ul>
</div>
<div id="myID3" class="analytics" data-attribute="hpg:unexpected">
  <ul>
    <li><a href="#">myID3 Link 1</a></li>
    <li><a href="#">myID3 Link 2</a></li>
    <li><a href="#">myID3 Link 3</a></li>
  </ul>  
</div>

答案 1 :(得分:0)

这是另一种方式:

document.querySelectorAll('li').forEach((item) => {
    item.addEventListener('click', (e) => {
        const index = Array.from(item.parentNode.children).indexOf((item))
        console.log(index);
    })
})