2010-10-25 2 views
0

Скажем, у меня есть базовая страница как так:Есть ли веб-элемент управления для динамического создания оглавления?

<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 /> для WebForms ASP.NET, который будет динамически генерировать оглавления, который выглядит примерно следующим образом (при визуализации на экране):

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

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

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

+1

Вы изучали использование карты сайта и затем визуализацию ее в форме вашего ТОС? http://www.15seconds.com/issue/041117.htm –

+0

Спасибо за предложение. TreeView выглядит как стандартный способ ASP.NET для этого. Тем не менее, я не вижу дублирующего элемента управления с SiteMapDataSource, что означает, что для того, чтобы этот подход работал, требуется довольно много кодирования. –

ответ

2

Мне нужно было сделать подобную вещь несколько дней назад и, хотя это не webcontrol, использовали 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; }.

+0

Чистый код. Мне это нравится. Контроллер на стороне сервера для создания оглавления по-прежнему будет полезен в некоторых случаях ... но для того, что я делаю прямо сейчас, выполнение этого на стороне клиента отлично работает. Благодаря! –

Смежные вопросы