addEventListener 中的 appendChild 在第一次申请后不工作
appendChild within addEventListener not working after first application
我有一个网页,其中有 1 到 N(默认 3 个,最多 7 个)交换 div 个元素——称为“会话”——选择一个后,其他元素应该消失(不被隐藏),即所选会话应取代前一个会话。有一个函数允许用户在 div 之间切换,并且在加载页面时调用该函数:
function generarSteps() {
var numSteps = 0;
for (let i = 1; i <= 7; i++) {
if (document.getElementById("switch_" + i).checked == true) {
numSteps = i;
break;
}
}
$('#num_sesiones').html('');
stepsString = "";
for (let j = 1; j <= numSteps; j++) {
stepsString += '' +
'<div class="uc-step" id="sesion_bubble_' + j + '">' +
'<div class="uc-step_head">' +
'<div class="uc-step_line"></div>' +
'<div class="uc-step_count" onclick="selectSesion(' + j + ')"></div>' +
'</div>' +
'<div class="uc-step_info">' +
'<div class="p-size--sm text-weight--bold">Sesión ' + j + '</div>' +
'</div>' +
'</div>';
}
$('#num_sesiones').append(stepsString);
selectSesion(1);
}
selectSesion:(部分,只有导致问题的部分)
function selectSesion(sesion) {
$('#materiales').empty();
materialesString = "" +
'<div class="p-16" style="height: 300px;">' +
'<div class="row mx-0" style="height: 156px">' +
'<div class="my-auto" style="width: 25%;">' +
'<div id="docs_existentes_' + (sesion - 1).toString() + '" class="uc-form-group m-0 py-16">' +
'<input id="myInput_' + sesion + '" type="text" class="uc-input-style doc_input mr-16" style="max-width: 255px;" placeholder="Seleccione...">' +
'</div>' +
'<div id="doc_nuevo_' + (sesion - 1).toString() + '"></div>' +
'</div>' +
'<div id="docs_selec_' + (sesion - 1).toString() + '" class="uc-card" style="width: 75%; background-color: #F6F6F6"></div>' +
'</div>' +
'</div>';
$('#materiales').append(materialesString);
documentosDropdown(sesion - 1);
documentosSeleccionados(sesion - 1);
}
documentosDropdown:
function documentosDropdown(num_sesion) {
docs = [];
for (let j = 0; j < documentos[num_sesion].length; j++) {
if (documentos[num_sesion][j].SELECCIONADO != 1) {
docs.push(documentos[num_sesion][j].NOM_ARCHIVO);
}
}
autocomplete(document.getElementById("myInput_" + (num_sesion + 1).toString()), docs, num_sesion);
}
这里是自动完成错误发生的地方:
function autocomplete(inp, arr, num_sesion) {
var currentFocus;
// for (var j = 1 ; j <= 7 ; j++) {
// $('#myInput_' + j).unbind('click');
// $('#myInput_' + j).unbind('input');
// }
inp.addEventListener("click", handler, false);
inp.addEventListener("input", handler, false);
function handler() {
alpha;
beta;
var i;
var val = this.value;
closeAllLists();
currentFocus = -1;
alpha = document.createElement("div");
// document.getElementById("myInput_" + (num_sesion + 1).toString()).parentNode.appendChild(alpha);
this.parentNode.appendChild(alpha);
alpha.setAttribute("id", "myInput_" + (num_sesion + 1).toString() + "_autocomplete-list");
alpha.setAttribute("class", "autocomplete-items mr-16");
alpha.style.maxHeight = "225px";
alpha.style.overflowY = "auto";
alpha.style.top = "61px";
for (i = 0; i < arr.length; i++) {
var indexOf = arr[i].toUpperCase().indexOf(val.toUpperCase());
if (indexOf > -1) {
beta = document.createElement("div");
beta.innerHTML = arr[i].substr(0, indexOf) + "<strong>" + arr[i].substr(indexOf, val.length) + "</strong>" + arr[i].substr(val.length + indexOf);
beta.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
alpha.appendChild(beta);
beta.addEventListener("click", function(e) {
selectDocumento(this.getElementsByTagName("input")[0].value, num_sesion);
inp.value = "";
closeAllLists();
});
}
}
}
function closeAllLists(elmnt) {
var x = document.getElementsByClassName("autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (elmnt != x[i] && elmnt != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
document.addEventListener("click", function(e) {
closeAllLists(e.target);
});
}
第一次加载页面时,selectSesion(1)(或我在其中放置的任何会话号)加载,当单击输入或在其中写入任何内容时,下拉菜单正常显示.但是,当我单击包含 selectSesion(n) 值的其他元素之一时,单击输入将不再弹出下拉列表,即使每当我在输入元素中写入时它都会出现。
只是为了测试,我在 autocomplete 函数之外声明了 alpha 变量,它表明确实创建了 alpha 并且甚至填充了 beta div 元素,但是它本身永远不会附加到输入元素的父节点,只有当它是第一个 selectSesion(1) 的原始下拉列表或每当我在输入元素中写入时。
我猜这与 javascript 的异步性质有关,但我对 javascript 还很陌生,所以我无法确定需要什么才能拥有该子节点附加到输入的父节点。
简而言之:
- 页面加载时选择会话 1
- 单击或键入 ID = myInput_1 的输入会附加一个 div 元素作为其下方的下拉列表
- 单击另一个 selectSesion(n) 按钮会生成其对应的输入,id = myInput_n
- 单击输入元素会创建本应附加到输入元素父节点的 div 元素,但从未附加它
- 在输入元素中键入 确实 但是附加说 div 元素
我希望它始终附加 div 元素,无论是在输入元素上单击还是输入。很抱歉太长了 post,但在解决手头的问题之前发生了很长的事件。
最坏的情况,我想知道是否有一种方法可以模拟该输入元素中的输入然后擦除它,以便至少激活“输入”事件,就像我之前说过,工作正常。
好的,错误是隧道视觉产生的问题。问题是,我的功能基于 w3schools 自动完成 javascript,其中自动完成功能仅在键入而不是单击输入元素时激活。
他们的自动完成功能甚至为整个文档添加了一个点击事件侦听器,它将关闭模拟的下拉元素,最终与输入元素的点击功能发生冲突,从而导致问题。
基本上我得改
document.addEventListener("click", function(e) {
closeAllLists(e.target);
});
在自动完成功能中
document.addEventListener("click", function(e) {
if (document.getElementsByClassName("doc_input")[0] != e.target) {
closeAllLists(e.target);
}
});
我有一个网页,其中有 1 到 N(默认 3 个,最多 7 个)交换 div 个元素——称为“会话”——选择一个后,其他元素应该消失(不被隐藏),即所选会话应取代前一个会话。有一个函数允许用户在 div 之间切换,并且在加载页面时调用该函数:
function generarSteps() {
var numSteps = 0;
for (let i = 1; i <= 7; i++) {
if (document.getElementById("switch_" + i).checked == true) {
numSteps = i;
break;
}
}
$('#num_sesiones').html('');
stepsString = "";
for (let j = 1; j <= numSteps; j++) {
stepsString += '' +
'<div class="uc-step" id="sesion_bubble_' + j + '">' +
'<div class="uc-step_head">' +
'<div class="uc-step_line"></div>' +
'<div class="uc-step_count" onclick="selectSesion(' + j + ')"></div>' +
'</div>' +
'<div class="uc-step_info">' +
'<div class="p-size--sm text-weight--bold">Sesión ' + j + '</div>' +
'</div>' +
'</div>';
}
$('#num_sesiones').append(stepsString);
selectSesion(1);
}
selectSesion:(部分,只有导致问题的部分)
function selectSesion(sesion) {
$('#materiales').empty();
materialesString = "" +
'<div class="p-16" style="height: 300px;">' +
'<div class="row mx-0" style="height: 156px">' +
'<div class="my-auto" style="width: 25%;">' +
'<div id="docs_existentes_' + (sesion - 1).toString() + '" class="uc-form-group m-0 py-16">' +
'<input id="myInput_' + sesion + '" type="text" class="uc-input-style doc_input mr-16" style="max-width: 255px;" placeholder="Seleccione...">' +
'</div>' +
'<div id="doc_nuevo_' + (sesion - 1).toString() + '"></div>' +
'</div>' +
'<div id="docs_selec_' + (sesion - 1).toString() + '" class="uc-card" style="width: 75%; background-color: #F6F6F6"></div>' +
'</div>' +
'</div>';
$('#materiales').append(materialesString);
documentosDropdown(sesion - 1);
documentosSeleccionados(sesion - 1);
}
documentosDropdown:
function documentosDropdown(num_sesion) {
docs = [];
for (let j = 0; j < documentos[num_sesion].length; j++) {
if (documentos[num_sesion][j].SELECCIONADO != 1) {
docs.push(documentos[num_sesion][j].NOM_ARCHIVO);
}
}
autocomplete(document.getElementById("myInput_" + (num_sesion + 1).toString()), docs, num_sesion);
}
这里是自动完成错误发生的地方:
function autocomplete(inp, arr, num_sesion) {
var currentFocus;
// for (var j = 1 ; j <= 7 ; j++) {
// $('#myInput_' + j).unbind('click');
// $('#myInput_' + j).unbind('input');
// }
inp.addEventListener("click", handler, false);
inp.addEventListener("input", handler, false);
function handler() {
alpha;
beta;
var i;
var val = this.value;
closeAllLists();
currentFocus = -1;
alpha = document.createElement("div");
// document.getElementById("myInput_" + (num_sesion + 1).toString()).parentNode.appendChild(alpha);
this.parentNode.appendChild(alpha);
alpha.setAttribute("id", "myInput_" + (num_sesion + 1).toString() + "_autocomplete-list");
alpha.setAttribute("class", "autocomplete-items mr-16");
alpha.style.maxHeight = "225px";
alpha.style.overflowY = "auto";
alpha.style.top = "61px";
for (i = 0; i < arr.length; i++) {
var indexOf = arr[i].toUpperCase().indexOf(val.toUpperCase());
if (indexOf > -1) {
beta = document.createElement("div");
beta.innerHTML = arr[i].substr(0, indexOf) + "<strong>" + arr[i].substr(indexOf, val.length) + "</strong>" + arr[i].substr(val.length + indexOf);
beta.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
alpha.appendChild(beta);
beta.addEventListener("click", function(e) {
selectDocumento(this.getElementsByTagName("input")[0].value, num_sesion);
inp.value = "";
closeAllLists();
});
}
}
}
function closeAllLists(elmnt) {
var x = document.getElementsByClassName("autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (elmnt != x[i] && elmnt != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
document.addEventListener("click", function(e) {
closeAllLists(e.target);
});
}
第一次加载页面时,selectSesion(1)(或我在其中放置的任何会话号)加载,当单击输入或在其中写入任何内容时,下拉菜单正常显示.但是,当我单击包含 selectSesion(n) 值的其他元素之一时,单击输入将不再弹出下拉列表,即使每当我在输入元素中写入时它都会出现。
只是为了测试,我在 autocomplete 函数之外声明了 alpha 变量,它表明确实创建了 alpha 并且甚至填充了 beta div 元素,但是它本身永远不会附加到输入元素的父节点,只有当它是第一个 selectSesion(1) 的原始下拉列表或每当我在输入元素中写入时。
我猜这与 javascript 的异步性质有关,但我对 javascript 还很陌生,所以我无法确定需要什么才能拥有该子节点附加到输入的父节点。
简而言之:
- 页面加载时选择会话 1
- 单击或键入 ID = myInput_1 的输入会附加一个 div 元素作为其下方的下拉列表
- 单击另一个 selectSesion(n) 按钮会生成其对应的输入,id = myInput_n
- 单击输入元素会创建本应附加到输入元素父节点的 div 元素,但从未附加它
- 在输入元素中键入 确实 但是附加说 div 元素
我希望它始终附加 div 元素,无论是在输入元素上单击还是输入。很抱歉太长了 post,但在解决手头的问题之前发生了很长的事件。
最坏的情况,我想知道是否有一种方法可以模拟该输入元素中的输入然后擦除它,以便至少激活“输入”事件,就像我之前说过,工作正常。
好的,错误是隧道视觉产生的问题。问题是,我的功能基于 w3schools 自动完成 javascript,其中自动完成功能仅在键入而不是单击输入元素时激活。
他们的自动完成功能甚至为整个文档添加了一个点击事件侦听器,它将关闭模拟的下拉元素,最终与输入元素的点击功能发生冲突,从而导致问题。
基本上我得改
document.addEventListener("click", function(e) {
closeAllLists(e.target);
});
在自动完成功能中
document.addEventListener("click", function(e) {
if (document.getElementsByClassName("doc_input")[0] != e.target) {
closeAllLists(e.target);
}
});