使用jQuery自动编号标题H1-H6

8

我阅读了相关帖子,但没有找到IE的解决方案,因此我请求一个jQuery解决方案来解决这个问题:

我有一些嵌套的分层标题,就像这样:

<h1> heading 1</h1> 
<h2> subheading 1</h2>
<h1> heading 2</h1> 
<h2> subheading 1</h2>
<h2> subheading 2</h2>

我需要类似于这样的自动生成标题输出:

1. heading 1
1.2 subheading 1
2. heading 2
2.1. subheading 1
2.2. subheading 2

有没有一种使用jQuery或类似工具在IE6+中实现这个的方法?

1
我倾向于基于这样的假设来工作:页面中应该只有一个 h1(即页面标题),这可能与您的结构相关或不相关。 - David Thomas
@David:我似乎记得 Google 也喜欢这样,所以这可能是相关的 :) 相应地调整脚本将是微不足道的。 - David Hedlund
@David,这与我之前听到的相符;...到了一个年龄,你学了很多东西,但却不记得它们来自哪里,感觉有点奇怪... :-/ - David Thomas
5个回答

7
这是我的看法:
var segments = [];

$(':header').each(function() { 

  var level = parseInt(this.nodeName.substring(1), 10);

  if(segments.length == level) {
    // from Hn to another Hn, just increment the last segment
    segments[level-1]++;
  } else if(segments.length > level) {
    // from Hn to Hn-x, slice off the last x segments, and increment the last of the remaining
    segments = segments.slice(0, level);
    segments[level-1]++;
  } else if(segments.length < level) {
    // from Hn to Hn+x, (should always be Hn+1, but I'm doing some error checks anyway)
    // add '1' x times.
    for(var i = 0; i < (level-segments.length); i++) {
      segments.push(1);
    }
  }

  $(this).text(segments.join('.') + '. ' + $(this).text());

});

Working example on all levels, H1 - H6


谢谢你的回答,Jerome的解决方案在我的环境中效果更好。 - cukabeka

6
另一种可能性。
var indices = [];

function addIndex() {
  // jQuery will give all the HNs in document order
  jQuery('h1,h2,h3,h4,h5,h6').each(function(i,e) {
      var hIndex = parseInt(this.nodeName.substring(1)) - 1;

      // just found a levelUp event
      if (indices.length - 1 > hIndex) {
        indices= indices.slice(0, hIndex + 1 );
      }

      // just found a levelDown event
      if (indices[hIndex] == undefined) {
         indices[hIndex] = 0;
      }

      // count + 1 at current level
      indices[hIndex]++;

      // display the full position in the hierarchy
      jQuery(this).prepend(indices.join(".")+" "+this.tagName);

  });
}

jQuery(document).ready(function() {
  addIndex();
});

啊,这也是我要采用的方法 :) 只是要注意:如果你有像 1.2.2.3.1. 非常深的标题 这样的东西,它可能紧接着就是 1.3. 子标题。删除最后一个索引并不总是足够的。 - David Hedlund
你说得对,我需要修复它。这样看起来就像是我克隆了你的答案;-)。已修复。 - Jerome WAGNER
谢谢,这给了我最好的结果。当选择器范围限制在特定区域时(如“#content h1,#content h2”),仍然有些棘手,但它有效!谢谢! - cukabeka
@honestor,h1-h7 可以表示为 :header,所以你可以简单地使用 #content :header。另一种方法是将上下文传递给选择器,这样它只会在该范围内搜索:$('h1,h2,h3,h4,h5,h6', $('#content')[0])。请注意,内容参数应该是 DOM 节点,而不是 jQuery 对象。因此需要 [0]。一个简单的 document.getElementById('content') 也可以完成工作! - David Hedlund

1

说实话,一旦我们能够获取跟随在每个<h1>标记后面且紧接着下一个<h1>标记之前的所有<h2>标记,问题就会得到解决,不是吗?

这段代码已经完成并正常工作。

$("h1").each(function(mainHeadIndex)
 {
     // Numbering the main heads
     $(this).html(mainHeadIndex +1 +'. ' + $(this).html());

     // Find all the h2 tags right under this particular main head
     $(this).nextUntil("h1").filter("h2").each(function(subIndex)
      {
          // calculate the right sub head number
          var newSubIndex = subIndex+1;
          // Numbering the sub heads
          $(this).html(mainHeadIndex +1 +'.'+ newSubIndex +$(this).html());
      });
  })

你可以在这个链接上进行测试

P.S:感谢你,MatejB,在你的帖子之前我不知道jsfiddle.com :)


谢谢David,代码现在已经更新以匹配您的场景。 - Mohammed Swillam
另一个增强功能是将此代码的范围限制在“h1”容器内,以不影响页面中的任何其他h1h2。可以通过以下方式之一来完成: 按容器的标签名称:$('divContainer h1') 或按容器的ID:$('#containerID').find('h1'),而不是使用原始代码行开始脚本。 - Mohammed Swillam
@Mohammed:不用担心格式问题。评论的标记语言是答案中的简化版本。当您添加评论时,可以单击“帮助”链接以获取格式说明。现在代码更好了,因为它不会在<p>标签和类似标签上触发,但您已将范围缩小到仅限于H1H2。虽然这些是他示例中唯一的标题,但标题中说的是H1-H6。我认为他想要像1.1.2.3.1.非常深的子标题这样的东西。 - David Hedlund
@david:没错,这就是我想要的。我喜欢你的方法可以定义选择器,但我仍然需要一些方式来覆盖h3-h6。 - cukabeka
@honestor:嗯,我的方法确实涵盖了h1-h6...? - David Hedlund

0

这段代码对我很有效:

var i = 0;
var j = 0;
$('h1').each(function(index, element){
    i++;
    $(element).text(i + '. ' + $(element).text());
j = 1; $(element).nextUntil('h1').each(function(subindex, subelement){ if (!$(this).is('h2')) return; // so subelements other than h2 can be left alone j++; $(subelement).text(i + '.' + j + '. ' + $(subelement).text()); }); });

在jsfiddle上的工作示例


将不是 h1 的每个元素都视为子标题。在 <h1>header</h1><h2>subheader</h2><p>paragraph 1</p><p>paragraph 2</p> 中,段落将分别以 1.21.3 开头。 - David Hedlund
@honestor 我认为David Hedlund给出了最好的解决方案 ;) - Matej Baćo

0


我认为你应该将H2子标题包装在DIV中,然后使用以下代码:

$(document).ready( function() {
    var result = 0;
    $('h1').each(function(index) {
        $(this).text((index + 1) + '. ' + $(this).text());
        var saveIndexNum = index + 1;
        $(this).next().find('h2').each(function(index) {
            $(this).text(saveIndexNum + '.' +(index + 1) + ' ' + $(this).text());
        });
    });
});

试一下



<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready( function() {
    var result = 0;
    $('h1').each(function(index) {
        $(this).text((index + 1) + '. ' + $(this).text());
        var saveIndexNum = index + 1;
        $(this).next().find('h2').each(function(index) {
            $(this).text(saveIndexNum + '.' +(index + 1) + ' ' + $(this).text());
        });
    });
});
</script>
<style>
h1
{
     color:red;
}
.subheading h2
{
    color:green;
}
.subheading
{
    background:#e2e2e2;
}
</style>
</head>
<body>
<h1> 标题 1</h1> 
<div class="subheading">
    <h2> 子标题 1.1</h2>
</div>
<h1> 标题 2</h1> 
<div class="subheading">
    <h2> 子标题 2.1</h2>
    <h2> 子标题 2.2</h2>
    <h2> 子标题 2.3</h2>
    <h2> 子标题 2.4</h2>
    <h2> 子标题 2.5</h2>
</div>
<h1> 标题 3</h1> 
<div class="subheading">
    <h2> 子标题 3.1</h2>
    <h2> 子标题 3.2</h2>
</div>
<h1> 标题 4</h1> 
<div class="subheading">
    <h2> 子标题 4.1</h2>
    <h2> 子标题 4.2</h2>
</div>
</body></html>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接