编辑textContent或innerHTML会终止eventListener
Editing the textContent or innerHTML kills eventListener
我从js开始,所以请原谅我明显的错误。我正在尝试用一些选项来重新创建可样式化标记的选择输入。
简单地说,我正在尝试做什么:
- 隐藏选择
- 用第一个选项的文本创建一个父div,并附加它,而不是原来的隐藏select
- 单击时添加eventListener以切换类(它显示和隐藏子元素)
- 使用原始隐藏选择的选项的值和文本创建内部div
- 为它们中的每一个添加eventListener以替换select值
这几行js和几行css让我很容易进行样式选择。
// Define select and options
var select = document.getElementById('select');
var children = select.children;
// Recreate select via divs and keep same class
select.style.display = 'none';
var selectNew = document.createElement('div');
selectNew.className = select.classList;
selectNew.textContent = select.children[0].text;
select.parentNode.insertBefore(selectNew, select);
selectNew.addEventListener('click', function() {
toggleChildren();
});
function toggleChildren() {
selectNew.classList.toggle('active');
}
// remap children
var childArray = [];
for (var i = 0; i < children.length; i++) {
var child = document.createElement('div');
child.innerHTML = select.children[i].text;
child.dataset.value = select.children[i].value;
selectNew.appendChild(child);
childArray.push(child);
child.addEventListener("click", function () {
selectChoice();
});
}
function selectChoice() {
var which = childArray.indexOf( event.target || event.srcElement);
select.value = children[which].value;
// selectNew.textContent = children[which].text;
}
.select {
position: relative;
width: 100%;
line-height: 3em;
background: #eee;
}
.select > div {
position: absolute;
display: none;
width: 100%;
}
.select > div:nth-child(1) {
top: 2em;
}
.select > div:nth-child(2) {
top: 4em;
}
.select > div:nth-child(3) {
top: 6em;
}
.select > div:nth-child(4) {
top: 8em;
}
.select > div:nth-child(5) {
top: 10em;
}
.select > div:hover {
background: #eee;
}
.select.active > div {
display: block;
}
<select name="sortby" id="select" class="select">
<option value="val1">Value 1</option>
<option value="val2">Value 2</option>
<option value="val3">Value 3</option>
<option value="val4">Value 4</option>
<option value="val5">Value 5</option>
</select>
每当我尝试更新父元素内的文本以通过显示所选选项的文本时
selectNew.textContent = children[which].text;
它会终止先前为此元素添加的事件侦听器。有人能帮我理解我做错了什么吗?我在事件听众的行为中缺少了什么?
您引用的行确实会导致问题,但不是因为它会杀死侦听器。它实际上用文本替换了selectNew
的全部内容。您想要的是替换第一个子节点的文本,即textContent节点。
如果您将线路更改为:
selectNew.firstChild.textContent = children[which].text;
那么一切都如预期的那样。
JSFiddle在这里。
回答奖金关于添加监听器以更改事件的附加问题:不能只在div上使用"change"事件的侦听器,只能在input等表单元素上使用。
然而,您可以检测到点击处理程序中的更改,如下所示:
function selectChoice() {
var which = childArray.indexOf(event.target || event.srcElement);
select.value = children[which].value;
if (selectNew.firstChild.textContent != children[which].text) {
alert('select value has been changed');
selectNew.firstChild.textContent = children[which].text;
}
}
此处更新了fiddle
它不会杀死你的事件,你通过设置textContent来删除你的选项元素,这样当你点击div时就没有什么可显示的了。你需要设置div的第一个TextNode的textContent。
// Define select and options
var select = document.getElementById('select');
var children = select.children;
// Recreate select via divs and keep same class
select.style.display = 'none';
var selectNew = document.createElement('div');
selectNew.className = select.classList;
selectNew.textContent = select.children[0].text;
select.parentNode.insertBefore(selectNew, select);
selectNew.addEventListener('click', function(e) {
toggleChildren(e);
});
function toggleChildren() {
selectNew.classList.toggle('active');
}
// remap children
var childArray = [];
for (var i = 0; i < children.length; i++) {
var child = document.createElement('div');
child.innerHTML = select.children[i].text;
child.dataset.value = select.children[i].value;
selectNew.appendChild(child);
childArray.push(child);
child.addEventListener("click", function () {
selectChoice();
});
}
function selectChoice() {
var which = childArray.indexOf( event.target || event.srcElement);
select.value = children[which].value;
//get the first textnode and set its textContent
selectNew.childNodes[0].textContent = children[which].text;
}
.select {
position: relative;
width: 100%;
line-height: 3em;
background: #eee;
}
.select > div {
position: absolute;
display: none;
width: 100%;
}
.select > div:nth-child(1) {
top: 2em;
}
.select > div:nth-child(2) {
top: 4em;
}
.select > div:nth-child(3) {
top: 6em;
}
.select > div:nth-child(4) {
top: 8em;
}
.select > div:nth-child(5) {
top: 10em;
}
.select > div:hover {
background: #eee;
}
.select.active > div {
display: block;
}
<select name="sortby" id="select" class="select">
<option value="val1">Value 1</option>
<option value="val2">Value 2</option>
<option value="val3">Value 3</option>
<option value="val4">Value 4</option>
<option value="val5">Value 5</option>
</select>
相关文章:
- 当使用Watchify时,Browserify+Babelify Gulp任务没有终止
- Eloquent JavaScript递归示例如何终止为返回1,但仍然输出指数值
- 我应该始终删除EventListener吗
- 删除对象时终止setInterval
- 使用react native检测应用程序终止
- 网络工作者突然终止工作
- eventListener出现JavaScript错误
- 未终止的字符串常量JavaScript
- EventListener只能工作一次
- 当传递innerHTML和(this.id)时,循环不会终止
- 函数输入上未终止的文本字符串
- Eventlistener in javascript to jQuery
- 未处理的 JavaScript 异常终止 MSAppHost/WWAHost.exe
- 如何终止捕获
- 终止所有正在进行的XHR请求
- 如何在fancybox终止加载后调用javascript函数
- 在javascript中,我正在使用EventListener,并且我得到了TypeError xyz = null
- JavaScript 中数据库数据的未终止字符串文字
- Javascript Eventlistener for Update / Change on Element / in
- 编辑textContent或innerHTML会终止eventListener