Автоматическая нумерация заголовков H1-H6 с использованием jQuery

Я прочитал похожие сообщения, но не нашел решения для 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+?


person cukabeka    schedule 26.02.2011    source источник
comment
Я склонен исходить из предположения, что на странице должен быть только один h1 (заголовок страницы), однако это может иметь или не иметь отношение к вашей структуре.   -  person David says reinstate Monica    schedule 26.02.2011
comment
@David: Кажется, я припоминаю, что Google тоже предпочитает это, так что это может иметь значение :) Было бы тривиально соответствующим образом настроить сценарий.   -  person David Hedlund    schedule 01.03.2011
comment
@ Дэвид, это соответствует тому, что я слышал ранее; ...странно дойти до возраста, когда ты что-то выучил и не можешь вспомнить, откуда это... :-/   -  person David says reinstate Monica    schedule 01.03.2011


Ответы (5)


другая возможность

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();
});
person Jerome WAGNER    schedule 26.02.2011
comment
А, это подход, который я тоже использую :) Просто примечание: если у вас есть что-то вроде 1.2.2.3.1. Very deep header, за ним может сразу следовать 1.3. Subheader. Удаление последнего индекса не всегда достаточно. - person David Hedlund; 26.02.2011
comment
Вы правы, мне нужно это исправить. таким образом, это действительно будет выглядеть так, как будто я клонировал ваш ответ ;-). Фиксированный. - person Jerome WAGNER; 26.02.2011
comment
Спасибо, это дает мне лучший результат. по-прежнему сложно, когда область действия селектора ограничена специальной областью, например (#content h1, #content h2), но это работает! Спасибо! - person cukabeka; 01.03.2011
comment
@honestor, h1-h7 можно выразить как :header, так что можно просто сделать #content :header. Другой подход состоит в том, чтобы передать контекст селектору, и в этом случае он будет искать только в этой области: $('h1,h2,h3,h4,h5,h6', $('#content')[0]). Обратите внимание, что параметр содержимого должен быть узлом DOM, а не объектом jQuery. Отсюда [0]. Простой document.getElementById('content') тоже справился бы с этой задачей! - person David Hedlund; 01.03.2011

Вот мой взгляд на это:

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());

});

Рабочий пример на всех уровнях, H1–H6

person David Hedlund    schedule 26.02.2011
comment
спасибо за ваш ответ, решение jeromes работает немного лучше в моей среде. - person cukabeka; 01.03.2011

честно говоря, проблема будет решена, как только мы сможем получить все теги <h2>, которые следуют сразу после каждого тега <h1> и непосредственно перед следующим тегом <h1>, верно?

Этот код сделал это и работает просто отлично

$("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 до вашего поста :)

person Mohammed Swillam    schedule 26.02.2011
comment
Спасибо, Дэвид, теперь код обновлен в соответствии с вашим сценарием. - person Mohammed Swillam; 26.02.2011
comment
другое усовершенствование здесь заключается в том, чтобы ограничить область действия этого кода контейнером 'h1', чтобы не затрагивать другие h1 или h2 на странице. это можно сделать, запустив скрипт с этой строкой вместо исходной: по имени тега контейнера: '$('divContainer h1')' или по идентификатору контейнера: '$('#containerID').find('h1' )' - person Mohammed Swillam; 26.02.2011
comment
@Mohammed: Не беспокойтесь о формате. Уценка комментариев — это упрощенная версия ответов. Вы можете щелкнуть ссылку «Помощь» при добавлении комментария, чтобы получить инструкции по форматированию. Теперь код лучше, поскольку он не срабатывает на тегах <p> и т.п., но вы сократили область действия до только H1 и H2. Хотя это единственные заголовки в его примере, заголовок говорит H1-H6. Я ожидаю, что он хочет что-то вроде 1.1.2.3.1. Очень глубокий подзаголовок - person David Hedlund; 26.02.2011
comment
@david: именно это я и ищу. Мне нравится в вашем подходе, что можно определить селектор, но мне все еще нужно как-то прикрыть h3-h6. - person cukabeka; 28.02.2011
comment
@honestor: хм, мой подход охватывает h1-h6...? - person David Hedlund; 28.02.2011

Это работает для меня:

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.

person Matej Baćo    schedule 26.02.2011
comment
Это рассматривает каждый отдельный элемент, который не является h1, как подзаголовок. в <h1>header</h1><h2>subheader</h2><p>paragraph 1</p><p>paragraph 2</p> абзацы будут начинаться с 1.2 и 1.3 соответственно. - person David Hedlund; 26.02.2011
comment
@honestor Я думаю, что Дэвид Хедлунд дал вам лучшее решение;) - person Matej Baćo; 28.02.2011


Я думаю, вам следует обернуть подзаголовки 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> heading 1</h1> 
<div class="subheading">
    <h2> subheading 1.1</h2>
</div>
<h1> heading 2</h1> 
<div class="subheading">
    <h2> subheading 2.1</h2>
    <h2> subheading 2.2</h2>
    <h2> subheading 2.3</h2>
    <h2> subheading 2.4</h2>
    <h2> subheading 2.5</h2>
</div>
<h1> heading 3</h1> 
<div class="subheading">
    <h2> subheading 3.1</h2>
    <h2> subheading 3.2</h2>
</div>
<h1> heading 4</h1> 
<div class="subheading">
    <h2> subheading 4.1</h2>
    <h2> subheading 4.2</h2>
</div>
</body></html>

person Owidat    schedule 26.02.2011