gpt4 book ai didi

javascript - 仅使用 JavaScript 的递归 HTML 表格树

转载 作者:行者123 更新时间:2023-11-30 14:35:38 24 4
gpt4 key购买 nike

我开发了点击父节点来显示它的子行。我只需要启用点击子数据应该打开它的子​​子行作为递归行或表树。任何人都可以添加您的逻辑来帮助我理解并帮助其他人吗?

document.getElementById("products").addEventListener("click", function(e) {
if (e.target.tagName === "A") {
e.preventDefault();
var row = e.target.parentNode.parentNode;
while ((row = nextTr(row)) && !/\bparent\b/ .test(row.className))
toggle_it(row);
}
});

function nextTr(row) {
while ((row = row.nextSibling) && row.nodeType != 1);
return row;
}

function toggle_it(item){
if (/\bopen\b/.test(item.className))
item.className = item.className.replace(/\bopen\b/," ");
else
item.className += " open";
}
tbody tr {
display : none;
}
tr.parent {
display : table-row;
}
tr.open {
display : table-row;
}
<!-- 
Bootstrap docs: https://getbootstrap.com/docs
-->

<div class="container">
<table class="table" id="products">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Destination</th>
<th>Updated on</th>
</tr>
</thead>
<tbody>
<tr class="parent">
<td><a href="#">+</a>Oranges</td>
<td>100</td>
<td>On Store</td>
<td>22/10</td>
</tr>
<tr>
<td>121</td>
<td>120</td>
<td>City 1</td>
<td>22/10</td>
</tr>
<tr>
<td>212</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
<tr>
<td>212</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
<tr class="parent">
<td><a href="#">+</a>Apples</td>
<td>100</td>
<td>On Store</td>
<td>22/10</td>
</tr>
<tr>
<td>120</td>
<td>120</td>
<td>City 1</td>
<td>22/10</td>
</tr>
<tr>
<td>120</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
</tbody>
</table>

</div>

最佳答案

更新的答案

我几乎更改了所有内容并简化了代码:

  • 自动添加切换按钮,
  • + 在父级打开时变为 -
  • 表格、打开和可见元素的类以及按钮作为参数传递,
  • 它可以用于多个表,

我已经在 GitHub 上用该代码创建了一个存储库:
https://github.com/TakitIsy/table-to-tree

/* ---- < MAIN FUNCTION > ---- */
function tableToTree(table_Selector, tr_OpenedClass, tr_VisibleClass, tr_ToggleButton) {

// Table elements variables
var table = document.querySelector(table_Selector);
var trs = document.querySelectorAll(table_Selector + " tr");

// Add the buttons above the table
var buttons = document.createElement('div');
buttons.innerHTML = '<button>[‒] All</button><button>[+] All</button>';
table.insertBefore(buttons, table.childNodes[0]);
buttons = buttons.querySelectorAll('button');
// Add the actions of these buttons
buttons[0].addEventListener("click", function() {
trs.forEach(function(elm) {
elm.classList.remove(tr_OpenedClass);
elm.classList.remove(tr_VisibleClass);
});
});
buttons[1].addEventListener("click", function() {
trs.forEach(function(elm) {
if (elm.innerHTML.includes(tr_ToggleButton))
elm.classList.add(tr_OpenedClass);
elm.classList.add(tr_VisibleClass);
});
});

// Next tr function
function nextTr(row) {
while ((row = row.nextSibling) && row.nodeType != 1);
return row;
}

// On creation, automatically add toggle buttons if the tr has childs elements
trs.forEach(function(tr, index) {
if (index < trs.length - 1) {
if (+tr.getAttribute("level") < +trs[index + 1].getAttribute("level")) {
var elm1 = tr.firstElementChild;
elm1.innerHTML = tr_ToggleButton + elm1.innerHTML;
}
}
});

// Use the buttons added by the function above
table.addEventListener("click", function(e) {

// Event management
if (!e) return;
if (e.target.outerHTML !== tr_ToggleButton) return;
e.preventDefault();

// Get the parent tr and its level
var row = e.target.closest("tr");
row.classList.toggle(tr_OpenedClass);
var lvl = +(row.getAttribute("level"));

// Loop to make childs visible/hidden
while ((row = nextTr(row)) && ((+(row.getAttribute("level")) == (lvl + 1)) || row.className.includes(tr_VisibleClass))) {
row.classList.remove(tr_OpenedClass);
row.classList.toggle(tr_VisibleClass);
}
});

}
/* ---- </ MAIN FUNCTION > ---- */

// Call the above main function to make the table tree-like
tableToTree('#myTable', 'opened', 'visible', '<span class="toggle"></span>');
tbody tr {
display: none;
}

tr[level="0"],
tr.visible {
display: table-row;
}

td {
background: #ccc;
padding: 4px 8px 4px 32px;
text-align: left;
}

tr[level="1"] td {
background: #ddd;
padding-left: 40px;
}

tr[level="2"] td {
background: #eee;
padding-left: 48px;
}

tr .toggle {
position: absolute;
left: 16px;
cursor: pointer;
}

.toggle::after {
content: "[+]";
}

.opened .toggle::after {
content: "[‒]";
}
<table id="myTable">
<tbody>
<tr level="0">
<td>Parent 1</td>
</tr>
<tr level="1">
<td>Match 1</td>
</tr>
<tr level="1">
<td>Match 2</td>
</tr>
<tr level="0">
<td>Parent 2</td>
</tr>
<tr level="1">
<td>Mismatch 1</td>
</tr>
<tr level="1">
<td>Mismatch 2</td>
</tr>
<tr level="2">
<td>Mismatch 2.1</td>
</tr>
</tbody>
</table>
<br>


⋅⋅⋅

旧答案

我玩了一下你的代码......
尝试尽可能多地使用现有的功能/方法,使代码更清晰,更易于阅读和理解。

…最后是那个片段:
(有关更多详细信息,请参阅我的代码中的注释)

document.getElementById("products").addEventListener("click", function(e) {
// I think using the not equal is nicer here, just my opinion… Less indenting.
if (!e) return; // Exit if null
if (e.target.tagName !== "A") return; // Exit if not A element

e.preventDefault();
var row = e.target.closest("tr"); // Better than parent parent!
var cls = row.classList[0]; // Get the first class name (the only one in our html)
var lvl = +(cls.slice(-1)) + 1; // Unary operator +1 on the last character
cls = cls.slice(0, -1) + lvl; // Replace the last char with lvl to get the class to be toggled

// Check if the row is of the class to be displayed OR if the row is already opened
// (so that clicking close on parent also closes sub-childs)
while ((row = nextTr(row)) && (row.className.includes(cls) || row.className.includes("open")))
row.classList.toggle("open"); // Better than the function you created, it already exists!
});

function nextTr(row) {
while ((row = row.nextSibling) && row.nodeType != 1);
return row;
}

// Select all the tr childs elements (all levels except 0
var allChilds = document.querySelectorAll("tr[class^=level]:not(.level0)");
// Added the below for buttons after comments
document.getElementById("openAll").addEventListener("click", function() {
allChilds.forEach(function(elm){
elm.classList.add("open");
});
});
document.getElementById("closeAll").addEventListener("click", function() {
allChilds.forEach(function(elm){
elm.classList.remove("open");
});
});
tbody tr {
display: none;
}


/* Simplified */

tr.level0,
tr.open {
display: table-row;
}


/* Added colors for better visibility */

tr.level0 {
background: #ccc;
}

tr.level1 {
background: #ddd;
}

tr.level2 {
background: #eee;
}


/* Added some more styling after comment */

tr td {
padding: 0.2em 0.4em;
}

tr td:first-of-type {
position: relative;
padding: 0.2em 1em;
}

tr td a {
color: inherit;
/* No special color */
text-decoration: inherit;
/* No underline */
position: absolute;
left: 0.25em;
}

tr.level1 td:first-of-type {
padding-left: 1.5em;
}

tr.level2 td:first-of-type {
padding-left: 2em;
}
<button id="openAll">+ All</button>
<button id="closeAll">- All</button>
<table class="table" id="products">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Destination</th>
<th>Updated on</th>
</tr>
</thead>
<tbody>
<tr class="level0">
<td><a href="#">+</a>Oranges</td>
<td>100</td>
<td>On Store</td>
<td>22/10</td>
</tr>
<tr class="level1">
<td>121</td>
<td>120</td>
<td>City 1</td>
<td>22/10</td>
</tr>
<tr class="level1">
<td><a href="#">+</a>212</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
<tr class="level2">
<td>212</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
<tr class="level2">
<td>212</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
<tr class="level0">
<td><a href="#">+</a>Apples</td>
<td>100</td>
<td>On Store</td>
<td>22/10</td>
</tr>
<tr class="level1">
<td>120</td>
<td>120</td>
<td>City 1</td>
<td>22/10</td>
</tr>
<tr class="level1">
<td><a href="#">+</a>120</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
<tr class="level2">
<td>120</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
<tr class="level2">
<td>120</td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
</tbody>
</table>

希望对您有所帮助!

关于javascript - 仅使用 JavaScript 的递归 HTML 表格树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50473899/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com