事件监听器附加到父元素,现在如何将点击的目标冒泡到特定的类名?

时间:2016-04-18 23:38:31

标签: javascript

我有一个正在侦听容器元素的事件监听器,我希望在单击时将活动类附加到它的任何子级(.container> div.active)。 (所以不要将活动类附加到.contain> div> ul.active)。

我的问题是我不完全确定.target到达div.diary的泡沫是什么?

http://jsbin.com/yereramaxe/edit?html,css,js,output



document.querySelector('.contain').addEventListener('click', diary);

function diary(e) {
	if (e.target.className === 'diary') { 
        //?.classList.add('active');
	}
}

* {
  font-size:0;
  padding:0;
  margin:0;
}
.diary {
  display:inline-block;
  background:red;
  width:33.33%;
  box-sizing:border-box;
  padding:10px;
}
li {
  font-size:18px;
}
ul {
  list-style-type: none;
}
div > ul > li {
  display:inline-block;
  width:33.33%;
}
.diary.active {
  background:blue;
}

<div class="contain">

  <div class="diary">
    <ul>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
    </ul>
  </div>

  <div class="diary">
    <ul>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
    </ul>
  </div>

  <div class="diary">
    <ul>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
      <li>
        <ul>
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </li>
    </ul>
  </div>

</div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

由于e.target将是实际发生点击的位置,您可以遍历该元素的父层次结构,直到找到相应的父diary div,然后将active类附加到那个父元素。

以下是一些代码,用于查找具有相应类名的父级:

function hasClass(elem, cls) {
    var str = " " + elem.className + " ";
    var testCls = " " + cls + " ";
    return(str.indexOf(testCls) !== -1) ;
}

function addClass(elem, cls) {
    if (!hasClass(elem, cls)) {
        var oldCls = elem.className;
        if (oldCls) {
            oldCls += " ";
        }
        elem.className = oldCls + cls;
    }
}

function removeClass(elem, cls) {
    var str = " " + elem.className + " ";
    elem.className = str.replace(" " + cls + " ", " ").replace(/^\s+|\s+$/g, "");
}

function findParentByClass(node, cls) {
    while (node && !hasClass(node, cls)) {
        node = node.parentNode;
    }
    return node;    
}

将它们放在一起就是这样:

document.querySelector('.contain').addEventListener('click', function(e) {
    var diary = findParentByClass(e.target, "diary");
    // add active class to parent diary div
    if (diary) {
        addClass(diary, "active");
    }
});

我猜你可能还想将其他.diary div标记为不再有效。如果是这种情况,那么你可以这样做:

document.querySelector('.contain').addEventListener('click', function(e) {
    var actives = document.querySelectorAll('.contain .active');
    for (var i = 0; i < actives.length; i++) {
        removeClass(actives[i], "active");
    }
    var diary = findParentByClass(e.target, "diary");
    // add active class to parent diary div
    if (diary) {
        addClass(diary, "active");
    }
});

当然,如果.classListaddClass()hasClass()函数与removeClass()兼容,那么您可以替换.classList方法。浏览器支持选择。

答案 1 :(得分:0)

从你的问题来看,我能理解的是,你想得到父母的分数。 &#39; li&#39;你点击了。 尝试这样做:

//Generic function to find an element or it's first ancestor with a given class name
function findParentWithClass(elem, className) {
    //You can make this much more safer by going only up to a specific parent container
    //If you want to be a bit more safer with checking classname read this http://stackoverflow.com/questions/5898656/test-if-an-element-contains-a-class
    if(elem.className == className) {
        console.log(elem);
        return elem;
    } else {
        findParentWithClass(elem.parentElement, className);
    } 
}

function diary(e) {
    findParentWithClass(e.target, 'diary');
}

document.querySelector('.contain').addEventListener('click', diary);

函数 findParentWithClass(element,className)检查元素是否具有特定的类名,如果为true,则返回元素,否则,它将转到父元素并检查父元素是否具有类这将以递归的方式发生,直到具有特定&#39; className&#39;找到了。