Существует ли веб-элемент управления для динамического создания оглавления? - PullRequest
0 голосов
/ 26 октября 2010

Скажем, у меня есть базовая страница примерно так:

<custom:TableOfContents />
<h1>Some Heading</h1>
  <h2>Foo</h2>
    <p>Lorem ipsum</p>
  <h2>Bar</h2>
    <p>Lorem ipsum</p>
  <h2>Baz</h2>
    <p>Lorem ipsum</p>
<h1>Another Heading</h2>
  <h2>Qux</h2>
    <p>Lorem ipsum</p>
  <h2>Quux</h2>
    <p>Lorem ipsum</p>

Предположим, что все теги заголовка существуют как элементы управления на стороне сервера.Существует ли какой-либо веб-элемент управления <custom:TableOfContents /> для веб-форм ASP.NET, который будет динамически генерировать оглавление, которое выглядит примерно так (при отображении на экране):

1. Some Heading
1.1. Foo
1.2. Bar
1.3. Baz
2. Another Heading
2.1. Qux
2.2. Quux

В идеале, каждая запись воглавление будет гиперссылкой на динамически сгенерированный якорь в соответствующем месте на странице.Кроме того, было бы неплохо, если бы текст каждого тега заголовка начинался с префикса его номера раздела.

Если не веб-элемент управления, есть ли какой-нибудь более простой способ сделать это?Имейте в виду, что многие теги заголовков будут создаваться элементами управления с привязкой к данным, поэтому ручное ведение оглавления не вариант.Кажется, что модель веб-форм идеально подходит для создания такого элемента управления, поэтому я удивлен, что еще не нашел его.

1 Ответ

2 голосов
/ 26 октября 2010

Мне нужно было сделать подобное несколько дней назад, и, хотя он и не был веб-контролем, использовал jQuery.

$(document).ready(buildTableOfContents);

function buildTableOfContents() {
    var headers = $('#content').find('h1,h2,h3,h4,h5,h6');
    var root, list;
    var previousLevel = 1;
    var depths = [0, 0, 0, 0, 0, 0];

    root = list = $('<ol />');

    for (var i = 0; i < headers.length; i++) {
        var header = headers.eq(i);
        var level = parseInt(header.get(0).nodeName.substring(1));

        if (previousLevel > level) {
            // Move up the tree
            for (var L = level; L < previousLevel; L++) {
                list = list.parent().parent();
                depths[L] = 0;
            }
        } else if (previousLevel < level) {
            // A sub-item
            for (var L = previousLevel; L < level; L++) {
                var lastItem = list.children().last();

                // Create an empty list item if we're skipping a level (e.g., h1 -> h3)
                if (lastItem.length == 0)
                    lastItem = $('<li />').appendTo(list);

                list = $('<ol />').appendTo(lastItem);
            }
        }

        depths[level - 1]++;

        // Grab the ID for the anchor
        var id = header.attr('id');
        if (id == '') {
            // If there is no ID, make a random one
            id = header.get(0).nodeName + '-' + Math.round(Math.random() * 1e10);
            header.attr('id', id);
        }

        var sectionNumber = depths.slice(0, level).join('.');

        list.append(
            $('<li />').append(
                $('<a />')
                    .text(sectionNumber + ' '+ header.text())
                    .attr('href', '#' + id)));

        previousLevel = level;
    }

    $('#table-of-contents').append(root);
}

Это создаст упорядоченный список и добавит его к #table-of-contents с соответствующей нумерацией (например, 1.1).Чтобы скрыть встроенную нумерацию списков, нужно немного CSS: #table-of-contents ol { list-style:none; }.

...