如何添加动态侦听器并获取目标的价值

时间:2018-07-20 03:10:18

标签: javascript html css

我创建了一个自定义下拉菜单,并希望获取其中被单击元素的文本内容。

Dropdown元素是与事件侦听器一样动态创建的,但是侦听器似乎无法正常工作。

下拉示例:

Dropdown example

我可以在开发工具中看到每个div上的侦听器。

子div的事件监听器:

Event listener of child div

下拉菜单中的第一个div会用输入的值填充输入值,而其他输入则不会。

(function() {
  let departments = ['Accounting', 'Human Resources', 'IT', 'Warehouse'];
  let element = document.getElementById('dd-Department');
  departments.forEach(v => {
    let div = document.createElement('div');
    div.appendChild(document.createTextNode(v));
    div.addEventListener('click', () => {
      element.parentNode.querySelector('input').value = v;
    });
    element.appendChild(div);
  });
})();
.form-question {
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin: 0 0 3rem;
  min-height: 3rem;
}

.form-question__title {
  color: #342357;
  font-size: 1.5rem;
  padding: 1rem;
}

.input-container {
  border-bottom: solid 2px #333333;
  position: relative;
}

input[readonly] {
  cursor: pointer;
}

.input-container input {
  border: none;
  box-sizing: border-box;
  outline: 0;
  padding: .75rem;
  position: relative;
  width: 100%;
}

.input-container:focus-within .dropdown {
  transform: scaleY(1);
}

.dropdown {
  background: #ffffff;
  box-shadow: 0 5px 12px #333333;
  left: 0;
  max-height: 300px;
  overflow-y: auto;
  padding: 0;
  position: absolute;
  right: 0;
  top: calc(100% + 2px);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform .3s;
  z-index: 10;
}

.dropdown div {
  border-bottom: 2px solid #777777;
  cursor: pointer;
  padding: 8px;
  z-index: 20;
}

.dropdown div:hover {
  background: #dddddd;
  font-weight: 800;
}
<div class="form-question">
  <div class="form-question__title">
    <span>Department</span>
  </div>
  <div class="form-question--dropdown input-container">
    <input type="text" name="Department" readonly="readonly"></input>
    <div id="dd-Department" class="dropdown"></div>
  </div>
</div>

我也尝试了事件委派,但是无法获得单击的div的文本内容。目标是目标div的父级,因此文本内容是所有子级值的组合。

let element = document.getElementById('dd-Department');
element.addEventListener('click', e => {
  if (e.target && e.target.classList.contains('dropdown')) {
    e.target.parentNode.parentNode.querySelector('input').value = e.target.textContent;
  }
}, true);

点击子div时的事件委派:

Event Delegation on click of child div

我在这里想念东西吗?

更新

感谢@dawn指出css是问题所在。 我已经通过更改来解决此问题

.input-container:focus-within .dropdown

.input-container.active .dropdown

并使用javascript添加活动类。

document.querySelectorAll('.input-container').forEach(v => {
    v.onclick = () => v.classList.toggle('active');
});

现在的问题是,在单击除输入容器之外的任何内容时,下拉列表仍处于活动状态。

以下内容有效,但感觉像是黑客。

document.querySelectorAll('.input-container').forEach(v => {
    v.addEventListener('focus', () => v.classList.add('active'), true);
    v.addEventListener('blur', () => setTimeout(() => v.classList.remove('active'), 75), true);
});

还有更优雅的解决方案吗?

1 个答案:

答案 0 :(得分:1)

这种情况是CSS的问题,当您单击div时,触发的第一件事是“ transform:scaleY(0)”,并且“ .dropdown”不可见,因此无法触发click事件。

请勿使用input:focus-within来控制下拉框的可见性,因为当您单击下拉框时,输入失去了焦点。