【问题标题】:Javascript for numbered table of contents用于编号目录的 Javascript
【发布时间】:2018-02-07 23:37:43
【问题描述】:

我正在整理一个 Sharepoint wiki,并且在每篇文章中,我都有一个类似于维基百科的标题目录,使用我认为是我在 InterWebz 上找到的 javascript。

<style>
#toc {
 display: table;
 border: 1px solid #aaa;
 background-color: #f9f9f9;
 font-size: 95%;
 padding: 7px;
}
#toc #tocHeader  {
 font-weight: bold;
 text-align: center;
}
#toc a:before { /* content:"• "; */ }
#toc a { line-height: 15px; margin: 10px; }
#toc .toc_Level1 { margin-left: 5px; }
#toc .toc_Level2 { margin-left: 15px; }
#toc .toc_Level3 { margin-left: 25px; }
#toc .toc_Level4 { margin-left: 35px; }
</style> 
<div id="toc"></div> 
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script type="text/javascript"> 
function GenerateTOC() {
  $("#toc").append('<p id="tocHeader">Contents</p>');
  $(".ms-rteElement-H1, .ms-rteElement-H1B, .ms-rteElement-H2, .ms-rteElement-H2B, .ms-rteElement-H3, .ms-rteElement-H3B, .ms-rteElement-H4, .ms-rteElement-H4B").each(function(i) {
 var currentNode = $(this);
  currentNode.attr("id", "title" + i);
 var linkClass = (currentNode.hasClass('ms-rteElement-H1') || currentNode.hasClass('ms-rteElement-H1B'))
   ? "toc_Level1" 
   : (currentNode.hasClass('ms-rteElement-H2') || currentNode.hasClass('ms-rteElement-H2B'))
   ? "toc_Level2" 
   : (currentNode.hasClass('ms-rteElement-H3') || currentNode.hasClass('ms-rteElement-H3B'))
   ? "toc_Level3" 
   : (currentNode.hasClass('ms-rteElement-H4') || currentNode.hasClass('ms-rteElement-H4B'))
   ? "toc_Level4" 
   : "";
  $("#toc").append("<a id='link'" + i + "' class='" + linkClass + "' href='#title" + i + "' title='" + currentNode.attr("tagName") + "'>" + currentNode.html() + "</a><br>");
  currentNode.append(" <a href='#tocHeader'>[top]</a>");
  });
}
_spBodyOnLoadFunctionNames.push('GenerateTOC');
</script>

我的目的是让目录为每个缩进级别单独编号,例如:

1. Heading 1   
  1.1. Heading 2    
  1.2. Heading 2   
2. Heading 1
  2.1. Heading 2   
  2.2. Heading 2

虽然我或多或少了解这段代码中发生了什么,但我完全不了解 javascript(或 Web 开发方面的知识 - 老实说,我不知道我现在是如何做到的),所以我几乎不知道如何实现它。我可以看到该函数已经有一个计数器来生成内部链接。

我的策略是添加两个额外的变量,比如 J 和 K(我只有两个缩进级别),其中 J 只会在它是 1 级标题(Element-H1,toc_Level1)时递增,而 K 会递增总是但会在处理 1 级标题(Element-H1,toc_Level1)时重置为 0,但是我完全不知道如何做到这一点。

编辑:

我添加了 javascript 的其余部分,但是它们只定义了目录的格式,所以我一开始并不认为它们相关。

网站结构如下:

<span class="ms-rteElement-Name">NAME</span>
<hr/>
<span class="ms-rteElement-Section">Section1</span>
<hr/>
<span class="ms-rteStyle-Text">Stuff</span>
<p><span class="ms-rteElement-Section">Section2</span></p>
<hr/>
<p><span class="ms-rteStyle-Text">Fluff</span></p>
<p><span class="ms-rteElement-H1">Heading 1</span></p>
<p><span class="ms-rteStyle-Text">Fluff</span></p>
<p><span class="ms-rteElement-H2">Heading 2</span></p>
<p><span class="ms-rteStyle-Text">Fluff</span></p>
<p><span class="ms-rteElement-H2">Heading 2</span></p>
<p><span class="ms-rteStyle-Text">Fluff</span></p>
<p><span class="ms-rteElement-H1">Heading 1</span></p>
<p><span class="ms-rteStyle-Text">Fluff</span></p>
<p><span class="ms-rteElement-H2">Heading 2</span></p>
<p><span class="ms-rteStyle-Text">Fluff</span></p>
<p><span class="ms-rteElement-H2">Heading 2</span></p>
<p><span class="ms-rteStyle-Text">Fluff</span></p>
<span class="ms-rteElement-Section">Section3</span>
<hr/>
<p><span class="ms-rteStyle-Text">More fluff</span></p>

上面给出的脚本完美地生成了目录,当然没有前面的数字。

【问题讨论】:

  • 你能提供一个你的wiki页面的例子吗?尝试编写一个与之配合使用的函数会更容易一些。
  • 请发布足够的minimal reproducible example 代码,以便我们可以重现您的问题。
  • 修改了附加信息。
  • 使用您的文档结构,无法创建指向特定部分的链接。您必须将回调绑定到 ToC。

标签: javascript css sharepoint tableofcontents


【解决方案1】:

一个可能的解决方案

function GenerateTOC() {
  $("#toc").append('<p id="tocHeader">Contents</p>');
  $(".ms-rteElement-H1, .ms-rteElement-H1B, .ms-rteElement-H2, .ms-rteElement-H2B, .ms-rteElement-H3, .ms-rteElement-H3B, .ms-rteElement-H4, .ms-rteElement-H4B").each(function(i) {
    var currentNode = $(this);
    currentNode.attr("id", "title" + i);
    var linkClass = (currentNode.hasClass('ms-rteElement-H1') || currentNode.hasClass('ms-rteElement-H1B')) ?
      "toc_Level1" :
      (currentNode.hasClass('ms-rteElement-H2') || currentNode.hasClass('ms-rteElement-H2B')) ?
      "toc_Level2" :
      (currentNode.hasClass('ms-rteElement-H3') || currentNode.hasClass('ms-rteElement-H3B')) ?
      "toc_Level3" :
      (currentNode.hasClass('ms-rteElement-H4') || currentNode.hasClass('ms-rteElement-H4B')) ?
      "toc_Level4" :
      "";
    $("#toc").append("<a id='link'" + i + "' class='" + linkClass + "' href='#title" + i + "' title='" + currentNode.attr("tagName") + "'>" + currentNode.html() + "</a><br>");
    currentNode.append(" <a href='#tocHeader'>[top]</a>");
  });

  // level 1
  $(".ms-rteElement-H1, .ms-rteElement-H1B").each(function(index, el) {
    $(this).html(index + '. ' + $(this).text());
    // level 2
    $('.ms-rteElement-H2, .ms-rteElement-H2B', this).each(function(idx, child) {
      $(this).html(index + '.' + idx + ' ' + $(this).text());
    });
  });
}

【讨论】:

    【解决方案2】:

    一种生成有序列表的解决方案,它应该能够处理更深层次的文档:

    function levelClassName(level) {
      if (typeof level !== "number") {
        throw new Error("Wrong argument type");
      }
    
      return "ms-rteElement-H".concat(level.toString(10));
    }
    
    function elementLink(element) {
      return $("<li></li>").text($(element).text());
    }
    
    function generateTOC() {
      var level = 1, // list level
        tocList = $("<ol></ol>"), // top level list
        lastElement = tocList;
    
      $("#toc").append('<p id="tocHeader">Contents</p>');
      $("#toc").append(tocList);
    
      $("span").each(function(index, value) {
        // make a jQuery object out of current element once instead of doing it
        // every time I want to use it
        var element = $(value),
          newElement;
    
        if (element.hasClass(levelClassName(level))) { // same level
          newElement = elementLink(value);
          // append inside list tag or next to last tag if it isn't a list
          lastElement[lastElement.prop("tagName") === "OL" ?
            "append" :
            "after"](newElement);
          lastElement = newElement;
        } else if (element.hasClass(levelClassName(level + 1))) { // deeper
          newElement = elementLink(value);
          // make a new list tag for the deeper level
          lastElement.append($("<ol></ol>").append(newElement));
          lastElement = newElement;
          level += 1;
        } else if (level - 1 >= 1 && // shallower
          element.hasClass(levelClassName(level - 1))) {
          newElement = elementLink(value);
          lastElement // list element
            .parent().parent() // -> list (on same level) -> list element above
            .after(newElement);
          lastElement = newElement;
          level -= 1;
        }
      });
    }
    
    $(document).ready(generateTOC);
    #toc {
      display: table;
      border: 1px solid #aaa;
      background-color: #f9f9f9;
      font-size: 95%;
      padding: 7px;
    }
    
    #toc #tocHeader {
      font-weight: bold;
      text-align: center;
    }
    
    #toc a:before {
      /* content:"• "; */
    }
    
    #toc a {
      line-height: 15px;
      margin: 10px;
    }
    
    #toc .toc_Level1 {
      margin-left: 5px;
    }
    
    #toc .toc_Level2 {
      margin-left: 15px;
    }
    
    #toc .toc_Level3 {
      margin-left: 25px;
    }
    
    #toc .toc_Level4 {
      margin-left: 35px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="toc"></div>
    <span class="ms-rteElement-Name">NAME</span>
    <hr/>
    <span class="ms-rteElement-Section">Section1</span>
    <hr/>
    <span class="ms-rteStyle-Text">Stuff</span>
    <p><span class="ms-rteElement-Section">Section2</span></p>
    <hr/>
    <p><span class="ms-rteStyle-Text">Fluff</span></p>
    <p><span class="ms-rteElement-H1">Heading 1</span></p>
    <p><span class="ms-rteStyle-Text">Fluff</span></p>
    <p><span class="ms-rteElement-H2">Heading 2</span></p>
    <p><span class="ms-rteStyle-Text">Fluff</span></p>
    <p><span class="ms-rteElement-H2">Heading 2</span></p>
    <p><span class="ms-rteStyle-Text">Fluff</span></p>
    <p><span class="ms-rteElement-H1">Heading 1</span></p>
    <p><span class="ms-rteStyle-Text">Fluff</span></p>
    <p><span class="ms-rteElement-H2">Heading 2</span></p>
    <p><span class="ms-rteStyle-Text">Fluff</span></p>
    <p><span class="ms-rteElement-H2">Heading 2</span></p>
    <p><span class="ms-rteStyle-Text">Fluff</span></p>
    <span class="ms-rteElement-Section">Section3</span>
    <hr/>
    <p><span class="ms-rteStyle-Text">More fluff</span></p>

    没有使链接可点击的代码。最好的方法是为每个标题提供唯一的 ID,然后在 ToC 中链接到它们。

    【讨论】:

      【解决方案3】:

      所以我终于想通了。不幸的是,没有一个答案给出了预期的答案(一个生成了一个 ToC,其中第二级项目符号也错过了相应的更高级别的项目符号,并且超链接功能也丢失了;另一个完全没有编号)。

      解决方案是在 GenerateTOC() 函数下添加其他变量

       var j = 0, k = 0;
      

      然后根据linkClass变量的值放入条件计数器和计数器重置,并放入单个文本变量中

       linkClass == "toc_Level1"     
         ? (j++, k = 0)       
         : linkClass == "toc_Level2"       
         ? k++       
         : "";
      
       var l = k == 0 
         ? (String(j) + ". ")   
         : (String(j) + "." + String(k) + ". ");
      

      然后在创建 ToC 条目的行中的“currentNode.html”前面添加了文本变量。

      <script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>    
      <script type="text/javascript">    
      function GenerateTOC() {    
       var j = 0, k = 0; // counters    
      
        $("#toc").append('<p id="tocHeader">Contents</p>');      
        $(".ms-rteElement-KD_Heading1, .ms-rteElement-KD_Heading2").each(function(i) {
      
       var currentNode = $(this);
      
        currentNode.attr("id", "title" + i);
      
       var linkClass = (currentNode.hasClass('ms-rteElement-KD_Heading1') || currentNode.hasClass('ms-rteElement-H1B'))    
         ? "toc_Level1"    
         : (currentNode.hasClass('ms-rteElement-KD_Heading2') || currentNode.hasClass('ms-rteElement-H2B'))    
         ? "toc_Level2"    
         : "";
      
       linkClass == "toc_Level1"     // runs the counters
         ? (j++, k = 0)       
         : linkClass == "toc_Level2"       
         ? k++       
         : "";
      
       var l = k == 0     // concatenates the counters
         ? (String(j) + ". ")       
         : (String(j) + "." + String(k) + ". ");
      
        $("#toc").append("<a id='link'" + i + "' class='" + linkClass + "' href='#title" + i + "' title='" + currentNode.attr("tagName") + "'>" + l + currentNode.html() + "</a><br>");    
        currentNode.append(" <a href='#tocHeader'>[top]</a>");    
        });    
      }    
      _spBodyOnLoadFunctionNames.push('GenerateTOC');    
      </script>
      

      【讨论】:

        猜你喜欢
        • 2018-01-14
        • 2011-02-26
        • 2020-07-21
        • 1970-01-01
        • 2011-11-20
        • 2011-07-28
        • 1970-01-01
        • 1970-01-01
        • 2019-02-19
        相关资源
        最近更新 更多