代码之家  ›  专栏  ›  技术社区  ›  James

将标题层次结构生成为有序列表

  •  6
  • James  · 技术社区  · 16 年前

    例如,您有一个标题结构如下的页面:

    <h1>Heading level 1</h1>
    
        <h2>Sub heading #1</h2>
    
        <h2>Sub heading #2</h2>
    
            <h3>Sub Sub heading</h3>
    
        <h2>Sub heading #3</h2>
    
            <h3>Sub Sub heading #1</h3>
    
            <h3>Sub Sub heading #2</h3>
    
                <h4>Sub Sub Sub heading</h4>
    
        <h2>Sub heading #4</h2>
    
            <h3>Sub Sub heading</h3>
    

    使用JavaScript(任何框架都可以),您将如何生成这样的列表:(使用嵌套列表)

    <ol>
        <li>Heading level 1
            <ol>
                <li>Sub heading #1</li>
                <li>Sub heading #2
                    <ol>
                        <li>Sub Sub heading</li>
                    </ol>
                </li>
                <li>Sub heading #3
                    <ol>
                        <li>Sub Sub heading #1</li>
                        <li>Sub Sub heading #2
                            <ol>
                                <li>Sub Sub Sub heading (h4)</li>
                            </ol>
                        </li>
                    </ol>
                </li>
                <li>Sub heading #4
                    <ol>
                        <li>Sub Sub heading</li>
                    </ol>
                </li>
            </ol>
        </li>
    </ol>
    

    解决方案需要遍历每个标题,并将其放入相应的嵌套列表中-我一直在对自己重复这一点,但我无法勾勒出任何东西!

    即使你脑子里有一套方法,但还没有时间编写代码,我还是想知道它!:)

    4 回复  |  直到 16 年前
        1
  •  4
  •   Prestaul    10 年前

    $('h1,h2,h3,h4,h5,h6') <h1> s将首先出现,然后是 <h2> s、 等等。当您使用逗号分隔的选择器时,还没有主框架按文档顺序返回元素。

    您可以通过向每个标题添加一个公共类来解决此问题。例如:

    <h1 class="heading">Heading level 1</h1>
    
        <h2 class="heading">Sub heading #1</h2>
    
        <h2 class="heading">Sub heading #2</h2>
    
            <h3 class="heading">Sub Sub heading</h3>
    
        <h2 class="heading">Sub heading #3</h2>
    
        ...
    

    现在是选择器 $('.heading')

    下面是使用jQuery的方法:

    var $result = $('<div/>');
    var curDepth = 0;
    
    $('h1,h2,h3,h4,h5,h6').addClass('heading');
    $('.heading').each(function() {
    
        var $li = $('<li/>').text($(this).text());
    
        var depth = parseInt(this.tagName.substring(1));
    
        if(depth > curDepth) { // going deeper
    
            $result.append($('<ol/>').append($li));
            $result = $li;
    
        } else if (depth < curDepth) { // going shallower
    
            $result.parents('ol:eq(' + (curDepth - depth - 1) + ')').append($li);
            $result = $li;
    
        } else { // same level
    
            $result.parent().append($li);
            $result = $li;
    
        }
    
        curDepth = depth;
    
    });
    
    $result = $result.parents('ol:last');
    
    // clean up
    $('h1,h2,h3,h4,h5,h6').removeClass('heading');
    

    $result <ol> .

    另外,请注意,这将处理 <h4> <h1> <h1> 接着是一个 <h4> (一次提升一个以上级别)。

        2
  •  3
  •   strager    16 年前

    首先,建一棵树。伪代码(因为我不擅长Javascript):

    var headings = array(...);
    var treeLevels = array();
    var treeRoots = array();
    
    foreach(headings as heading) {
        if(heading.level == treeLevels.length) {
            /* Adjacent siblings. */
    
            if(heading.level == 1) {
                treeRoots[] = heading;  // Append.
            } else {
                treeLevels[treeLevels.length - 2].children[] = heading;  // Add child to parent element.
            }
    
            treeLevels[treeLevels.length - 1] = heading;
        } else if(heading.level > treeLevels.length) {
            /* Child. */
    
            while(heading.level - 1 > treeLevels.length) {
                /* Create dummy headings if needed. */
                treeLevels[] = new Heading();
            }
    
            treeLevels[] = heading;
        } else {
            /* Child of ancestor. */
    
            treeLevels.remove(heading.level, treeLevels.length - 1);
    
            treeLevels[treeLevels.length - 1].children[] = heading;
            treeLevels[] = heading;
        }
    }
    

    function buildList(root) {
        var li = new LI(root.text);
    
        if(root.children.length) {
            var subUl = new UL();
            li.children[] = subUl;
    
            foreach(root.children as child) {
                subUl.children[] = buildList(child);
            }
        }
    
        return li; 
    }
    

    最后,插入 LI buildList 变成 UL treeRoots .

    在jQuery中,可以按如下顺序获取标题元素:

    var headers = $('*').filter(function() {
        return this.tagName.match(/h\d/i);
    }).get();
    
        3
  •  2
  •   Jan Kyu Peblik    9 年前

    我可以想象很多情况下,你可能会过度考虑这一点。对于许多情况,您实际上只需要 外貌 而不是实际重新生成的HTML层次结构本身,您可以对其执行以下简单操作:

    #nav li.h1 { padding: 0 0 0  0px; } #nav li.h1:before { content: 'h1 '; }
    #nav li.h2 { padding: 0 0 0 10px; } #nav li.h2:before { content: 'h2 '; }
    #nav li.h3 { padding: 0 0 0 20px; } #nav li.h3:before { content: 'h3 '; }
    #nav li.h4 { padding: 0 0 0 30px; } #nav li.h4:before { content: 'h4 '; }
    #nav li.h5 { padding: 0 0 0 40px; } #nav li.h5:before { content: 'h5 '; }
    #nav li.h6 { padding: 0 0 0 50px; } #nav li.h6:before { content: 'h6 '; }
    

    for (i=1; i<=6; i++) {
        var headers = document.getElementsByTagName('h'+i);
        for (j=0; j<headers.length; j++) {
            headers[j].className = 'h';
        }
    }
    var headers = document.getElementsByClassName('h');
    var h1 = document.getElementsByTagName('h1')[0];
    h1.parentNode.insertBefore(document.createElement('ul'),h1.nextSibling);
    h1.nextSibling.id = 'nav';
    for (i=0; i<headers.length; i++) {
        document.getElementById('nav').innerHTML += '<li class="'+headers[i].tagName.toLowerCase()+'">'+headers[i].innerHTML+'</li>';
    }
    
        4
  •  -1
  •   willy wonka    9 年前

    这将把所有h1-h6标记选择到文档的docElTgt DOM部分,并将在html文档中考虑订单标题

    var hItemsList = docElTgt.querySelectorAll('h1, h2, h3, h4, h5, h6');
    

    docElTgt = document.body;
    docElTgt = anyelement.id;
    

    选择所有标题后,可以应用算法使层次结构成为其他用户显示的有序列表