我想使用标题创建树。
例:
<h1>Wow</h1>
<h2>Blablablub</h2>
<p>Lorem Ipsum...</p>
<h1>Lalalala</h1>
<p>Lorem Ipsum...</p>
<h1>Ble</h1>
<h2>Test</h2>
<h3>Third</h3>
<p>Lorem Ipsum...</p>
应创建此列表:
<ul>
<li>
<a>Wow</a>
<ul>
<li>
<a>Blablablub</a>
</li>
</ul>
</li>
<li>
<a>Lalalala</a>
</li>
<li>
<a>Ble</a>
<ul>
<li>
<a>Test</a>
<ul>
<li>
<a>Third</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
a
标记应具有自定义ID,但这对这个问题并不重要。我试图这样做,但我无法弄清楚。这是我尝试过的:function find_titles(find_num, element, prefix=""){
temp_list = $("<ul></ul>");
element.find(`${prefix}h${find_num}`).each(function(i, object){
let text = $(object).text();
let id = text.replace(/[^0-9a-zA-Z]/gi, "") + random_chars();
$(object).attr("id", id);
if ($(object).next().prop("tagName").toLowerCase() == `h${find_num + 1}`){
console.log($(object));
next_titles = find_titles(find_num + 1, $(object), "+ ")[0].innerHTML;
} else {
next_titles = "";
}
$(`<li><a href="#${id}">${text}</a>${next_titles}</li>`).appendTo(temp_list);
});
return temp_list;
}
编辑
这个:
<h1>First</h1>
<h2>Second</h2>
<p>Lorem Ipsum</p>
<h3>Third</h3>
通常应转换为:
<ul>
<li>
<a>First</a>
<ul>
<li>
<a>Second</a>
</li>
</ul>
</li>
<li>
<a>Third</a>
</li>
</ul>
我不在乎第一个是
h1
h2
还是h3
。在文本中,它仅对样式很重要,但在树中则不重要。 最佳答案
您可以首先清除数据,以仅获取heading
节点及其编号和文本。之后,您可以循环使用每个级别的数组和索引号,根据级别循环数据并构建树结构。
function tree(data) {
data = Array.from(data).reduce((r, e) => {
const number = e.nodeName.match(/\d+?/g);
if(number) r.push({ text: e.textContent, level: +number })
return r;
}, [])
const result = $("<ul>")
const levels = [
[], result
]
data.forEach(({ level, text }) => {
const li = $("<li>")
const a = $("<a>", { text, href: text })
levels[level + 1] = $('<ul>')
li.append(a)
li.append(levels[level + 1]);
levels[level].append(li)
})
return result;
}
const result = tree($("body > *"));
$("body").html(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Wow</h1>
<h2>Blablablub</h2>
<p>Lorem Ipsum...</p>
<h1>Lalalala</h1>
<p>Lorem Ipsum...</p>
<h1>Ble</h1>
<h2>Test</h2>
<h3>Third</h3>
<p>Lorem Ipsum...</p>
您也可以使用一种
reduce
方法执行此操作,如果元素为标题,则将其添加到树中。function tree(data) {
const result = $("<ul>")
const levels = [
[], result
]
Array.from(data).reduce((r, { textContent: text, nodeName }) => {
const number = nodeName.match(/\d+?/g);
const level = number ? +number : null;
if(level) {
const li = $('<li>').append($("<a>", { text, href: text }))
r.push({ level: r[level + 1] = $('<ul>') })
r[level].append(li.append(levels[level + 1]))
}
return r;
}, levels)
return result;
}
const result = tree($("body > *"));
$("body").html(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Wow</h1>
<h2>Blablablub</h2>
<p>Lorem Ipsum...</p>
<h1>Lalalala</h1>
<p>Lorem Ipsum...</p>
<h1>Ble</h1>
<h2>Test</h2>
<h3>Third</h3>
<p>Lorem Ipsum...</p>