javascript - 获取所有标题并递归创建树

标签 javascript jquery html

我想使用标题创建一棵树。

例子:

<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>

关于javascript - 获取所有标题并递归创建树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56715754/

相关文章:

jquery - eq() 选择每 4 个类别

css - Bootstrap 4 轮播中的内容对齐/禁用左侧指示器

javascript - jQuery - 如何委托(delegate)切换

javascript - Angular js : $injector:modulerr Module Error

javascript - j_security_check 使用 ajax

c# - 如何在 MVC 中使用 Javascript/AJAX 将整个对象传递给 Controller ​​?

jquery - 如何使用 jquery sortable 保存表行的顺序而不使用 ".toArray()"或 ".serialize()"?

javascript - ReactJS + Material-UI : How to use Material-UI’s FlatButton and Dialog in each TableRow?

javascript - 在网站 HTML 页面上搜索文本

javascript regexp & 结果中的额外字符