我正在使用数组值创建元素的动态树,该数组值按 Parent 的属性值维护级别,该属性值与元素 Button Text 匹配 我后来用作手风琴。
这里出现的问题是,它不会为具有该特定文本
的所有元素创建元素我什至使用了 For Loop,然后尝试使用 nextElementSibling 插入,如下面的函数所示
function appendSymptomToForm(symptom, symptomElements, container) {
if (symptom.parent === 'none') {
symptomForm.appendChild(container);
} else {
var aTags = document.getElementsByTagName("button");
var searchText = symptom.parent;
var found;
for (var i = 0; i < aTags.length; i++) {
if (aTags[i].textContent == searchText) {
found = aTags[i].nextElementSibling;
found.insertBefore(container, found.nextElementSibling);
}
}
}
console.log(`Symptom ${symptom.text} appended to the form.`);
}
下面正是附加子元素的代码行。
found.insertBefore(container, found.nextElementSibling);
下面我创建了 fiddle,它可以让您充分理解,我在名为 window.symptomData 的数组中有 3 个级别。 每个元素根据其父属性
添加例如注意第二级B:
{ 深度:3,文本:'第三级 B',父级:'第二级 B',工具提示: “描述简单的矿石周期”}
在这里你会看到有多个第二级B的按钮,但它只在最后一个元素下添加了第三级
请参考fiddle中的函数appendSymptomToForm,其中 它确实appendChild
window.symptomData = [
{ depth: 0, text: 'De aproximativ', parent: 'none', tooltip: 'Perioadă nespecificată de timp, folosită pentru estimări' },
{ depth: 1, text: '1', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 1, text: '2', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 1, text: '3', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 1, text: '4', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată de timp' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în ani' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în săptămâni' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în ani' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în săptămâni' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în ani' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în săptămâni' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în ani' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de ore' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de zile' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de săptămâni' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de luni' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de ani' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de ore' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de zile' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de săptămâni' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de luni' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de ani' },
];
// script.js
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded event triggered, initializing symptoms setup...');
const symptomData = window.symptomData; // Now pulling from the global variable set by sd.js
const symptomForm = document.getElementById('symptomForm');
if (!symptomForm) {
console.error('Failed to find symptom form on the page.');
return;
}
let symptomElements = {};
const tooltipDiv = document.createElement('div');
setupTooltipDiv(tooltipDiv);
document.body.appendChild(tooltipDiv);
symptomData.forEach(symptom => {
const container = document.createElement('div');
setupSymptomContainer(symptom, container);
const button = document.createElement('button');
setupSymptomButton(symptom, button, container);
const childrenContainer = document.createElement('div');
setupChildrenContainer(childrenContainer, container);
symptomElements[symptom.text] = { button, container, childrenContainer };
setupButtonEvents(button, childrenContainer);
appendSymptomToForm(symptom, symptomElements, container);
});
setupSendButton();
});
function setupTooltipDiv(tooltipDiv) {
tooltipDiv.id = 'tooltipDiv';
tooltipDiv.style = "position: fixed; bottom: 20px; left: 20px; padding: 10px; " +
"background-color: rgba(0, 0, 0, 0.75); color: white; border-radius: 5px; display: none;";
console.log('Tooltip div setup completed.');
}
function setupSymptomContainer(symptom, container) {
container.className = `symptom-instance depth-${symptom.depth}`;
console.log(`Setup container for symptom: ${symptom.text}`);
}
function setupSymptomButton(symptom, button, container) {
button.textContent = symptom.text;
button.className = 'symptom-button';
button.title = symptom.tooltip;
container.appendChild(button);
console.log(`Button created for symptom: ${symptom.text}`);
}
function setupChildrenContainer(childrenContainer, container) {
childrenContainer.className = 'sub-symptoms hidden';
container.appendChild(childrenContainer);
console.log('Children container setup completed.');
}
function setupButtonEvents(button, childrenContainer) {
button.onclick = () => {
childrenContainer.classList.toggle('hidden');
button.classList.toggle('pressed');
scrollToButton(button);
console.log(`Visibility toggled for: ${button.textContent}, New state: ${childrenContainer.className}`);
};
button.addEventListener('touchstart', () => showTooltip(button, button.title), { passive: true });
button.addEventListener('touchend', hideTooltip, { passive: true });
}
function appendSymptomToForm(symptom, symptomElements, container) {
if (symptom.parent === 'none') {
symptomForm.appendChild(container);
} else {
var aTags = document.getElementsByTagName("button");
var searchText = symptom.parent;
var found;
for (var i = 0; i < aTags.length; i++) {
if (aTags[i].textContent == searchText) {
found = aTags[i].nextElementSibling;
found.insertBefore(container, found.nextElementSibling);
}
}
}
console.log(`Symptom ${symptom.text} appended to the form.`);
}
function scrollToButton(button) {
const buttonRect = button.getBoundingClientRect();
const visibleAreaStart = window.innerHeight / 4;
const scrollYOffset = buttonRect.top - visibleAreaStart + window.scrollY;
window.scrollTo({
top: scrollYOffset,
behavior: 'smooth'
});
console.log(`Scrolled to button: ${button.textContent}`);
}
function setupSendButton() {
const sendButton = document.createElement('button');
sendButton.textContent = 'Copiaza Selectate';
sendButton.addEventListener('click', () => {
const selectedSymptoms = Array.from(document.querySelectorAll('.symptom-button.pressed'))
.map(btn => btn.textContent.trim())
.join(', ');
navigator.clipboard.writeText(selectedSymptoms)
.then(() => {
console.log('Selected symptoms copied to clipboard.');
alert('Selected symptoms copied to clipboard.');
})
.catch(err => {
console.error('Error copying to clipboard:', err);
alert('Failed to copy symptoms. See console for errors.');
});
});
document.body.appendChild(sendButton);
console.log('Send button setup completed.');
}
function showTooltip(button, text) {
const tooltipDiv = document.getElementById('tooltipDiv');
tooltipDiv.textContent = text;
tooltipDiv.style.display = 'block';
console.log(`Tooltip shown for ${button.textContent}: ${text}`);
}
function hideTooltip() {
const tooltipDiv = document.getElementById('tooltipDiv');
tooltipDiv.style.display = 'none';
console.log('Tooltip hidden.');
}
<div id="symptomForm">
</div>
问题出在插入
appendSymptomToForm
(子级)的 container
函数中。
这段代码只是将容器从一个地方转移到另一个地方(第一个父容器,第二个容器,...第五个容器)。这是一个孩子正在被移动。
for (var i = 0; i < aTags.length; i++) {
if (aTags[i].textContent == searchText) {
found = aTags[i].nextElementSibling;
found.insertBefore(container, found.nextElementSibling);
}
}
您需要做的是在插入之前拥有
container
(子级)的副本/克隆。比如:
var clonedContainer = container.cloneNode(true);
这就是必须插入的子项:
found.insertBefore(clonedContainer, found.nextElementSibling);
你的函数应该是这样的:
function appendSymptomToForm(symptom, symptomElements, container) {
if (symptom.parent === 'none') {
symptomForm.appendChild(container);
} else {
var aTags = document.getElementsByTagName("button");
var searchText = symptom.parent;
var found;
for (var i = 0; i < aTags.length; i++) {
if (aTags[i].textContent == searchText) {
var clonedContainer = container.cloneNode(true);
found = aTags[i].nextElementSibling;
found.insertBefore(clonedContainer, found.nextElementSibling);
}
}
}
console.log(`Symptom ${symptom.text} appended to the form.`);
}
这是工作代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="symptomForm">
</div>
<script>
window.symptomData = [
{ depth: 0, text: 'De aproximativ', parent: 'none', tooltip: 'Perioadă nespecificată de timp, folosită pentru estimări' },
{ depth: 1, text: '1', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 1, text: '2', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 1, text: '3', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 1, text: '4', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată de timp' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în ani' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în săptămâni' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în ani' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în săptămâni' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în ani' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în ore' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în zile' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în săptămâni' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în luni' },
{ depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în ani' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de ore' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de zile' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de săptămâni' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de luni' },
{ depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de ani' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de ore' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de zile' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de săptămâni' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de luni' },
{ depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de ani' },
];
// script.js
document.addEventListener('DOMContentLoaded', function () {
console.log('DOMContentLoaded event triggered, initializing symptoms setup...');
const symptomData = window.symptomData; // Now pulling from the global variable set by sd.js
const symptomForm = document.getElementById('symptomForm');
if (!symptomForm) {
console.error('Failed to find symptom form on the page.');
return;
}
let symptomElements = {};
const tooltipDiv = document.createElement('div');
setupTooltipDiv(tooltipDiv);
document.body.appendChild(tooltipDiv);
symptomData.forEach(symptom => {
const container = document.createElement('div');
setupSymptomContainer(symptom, container);
const button = document.createElement('button');
setupSymptomButton(symptom, button, container);
const childrenContainer = document.createElement('div');
setupChildrenContainer(childrenContainer, container);
symptomElements[symptom.text] = { button, container, childrenContainer };
setupButtonEvents(button, childrenContainer);
appendSymptomToForm(symptom, symptomElements, container);
});
setupSendButton();
});
function setupTooltipDiv(tooltipDiv) {
tooltipDiv.id = 'tooltipDiv';
tooltipDiv.style = "position: fixed; bottom: 20px; left: 20px; padding: 10px; " +
"background-color: rgba(0, 0, 0, 0.75); color: white; border-radius: 5px; display: none;";
console.log('Tooltip div setup completed.');
}
function setupSymptomContainer(symptom, container) {
container.className = `symptom-instance depth-${symptom.depth}`;
console.log(`Setup container for symptom: ${symptom.text}`);
}
function setupSymptomButton(symptom, button, container) {
button.textContent = symptom.text;
button.className = 'symptom-button';
button.title = symptom.tooltip;
container.appendChild(button);
console.log(`Button created for symptom: ${symptom.text}`);
}
function setupChildrenContainer(childrenContainer, container) {
childrenContainer.className = 'sub-symptoms hidden';
container.appendChild(childrenContainer);
console.log('Children container setup completed.');
}
function setupButtonEvents(button, childrenContainer) {
button.onclick = () => {
childrenContainer.classList.toggle('hidden');
button.classList.toggle('pressed');
scrollToButton(button);
console.log(`Visibility toggled for: ${button.textContent}, New state: ${childrenContainer.className}`);
};
button.addEventListener('touchstart', () => showTooltip(button, button.title), { passive: true });
button.addEventListener('touchend', hideTooltip, { passive: true });
}
function appendSymptomToForm(symptom, symptomElements, container) {
if (symptom.parent === 'none') {
symptomForm.appendChild(container);
} else {
var aTags = document.getElementsByTagName("button");
var searchText = symptom.parent;
var found;
for (var i = 0; i < aTags.length; i++) {
if (aTags[i].textContent == searchText) {
var clonedContainer = container.cloneNode(true);
found = aTags[i].nextElementSibling;
found.insertBefore(clonedContainer, found.nextElementSibling);
}
}
}
console.log(`Symptom ${symptom.text} appended to the form.`);
}
function scrollToButton(button) {
const buttonRect = button.getBoundingClientRect();
const visibleAreaStart = window.innerHeight / 4;
const scrollYOffset = buttonRect.top - visibleAreaStart + window.scrollY;
window.scrollTo({
top: scrollYOffset,
behavior: 'smooth'
});
console.log(`Scrolled to button: ${button.textContent}`);
}
function setupSendButton() {
const sendButton = document.createElement('button');
sendButton.textContent = 'Copiaza Selectate';
sendButton.addEventListener('click', () => {
const selectedSymptoms = Array.from(document.querySelectorAll('.symptom-button.pressed'))
.map(btn => btn.textContent.trim())
.join(', ');
navigator.clipboard.writeText(selectedSymptoms)
.then(() => {
console.log('Selected symptoms copied to clipboard.');
alert('Selected symptoms copied to clipboard.');
})
.catch(err => {
console.error('Error copying to clipboard:', err);
alert('Failed to copy symptoms. See console for errors.');
});
});
document.body.appendChild(sendButton);
console.log('Send button setup completed.');
}
function showTooltip(button, text) {
const tooltipDiv = document.getElementById('tooltipDiv');
tooltipDiv.textContent = text;
tooltipDiv.style.display = 'block';
console.log(`Tooltip shown for ${button.textContent}: ${text}`);
}
function hideTooltip() {
const tooltipDiv = document.getElementById('tooltipDiv');
tooltipDiv.style.display = 'none';
console.log('Tooltip hidden.');
}
</script>
</body>
</html>