Create a Table of Contents automatically



2016년 8월 18일에 게시됨

Much like the author of this article, our company needs a way to automatically generate a table of contents for large articles. After finding out we can use jQuery, I put together a script that will automagically create a tiered table of contents based on the Header tags used in the article.

All you need to do is paste the Javascript in this page into the Javascript section of your Articles:

 

Click on the JS tab, then paste in the code at the end:

 

That should do it.. as long as you've used proper heading tags (H1, H2, etc), a Table of Contents will be created any time you load the article.

You can see a live example here: http://codepen.io/ngalluzzo/pen/kXqyVQ?editors=1010


3

55

댓글 55개

Hi Vladan,

Thanks for the response. A good example of an article in our Help Center with multiple levels of headers can be found here:

[Link removed after the issue was resolved]

0


Hi Ariana, for debugging it would be much easier if any chance you can share a link to your article or help center here.

0


Hello All,

I'm using the code Lily Svetnik posted June 25, 2018, t 10:58, but nothing is happening to my articles. Am I posting the code in the correct place? I've added it to the end of the "Script.js" asset, as shown below:

 

0


Thanks for sharing the resolved code, Lily!

0


Hi Jessie!

I was using the latest code that was posted here. Apparently, it wasn't working mostly because of syntax errors and other minor issues. 

We've corrected and slightly modified the script, it's working perfectly fine now and I'm loving it!

 

Here's my version if anyone else is looking for a solution:

 

/*** Table of contents code ***/
var $headers = $('.article-body:first h1');

if ($headers.length == 0) $headers = $('.article-body:first h2');

if ($headers.length > 0) {
var $toc = $('<div class="toc" style="margin-bottom: 25px">');
var $firstUl = $('<ul>');
var $currentUl = $firstUl;
var previous_level = 1;
var $arrayUl = [];


$firstUl.appendTo($toc);
$('#table-of-contents').length > 0 ? $toc.appendTo('#table-of-contents') : $toc.prependTo('.article-body:first');

// start with first H1
insertHeading($headers[0]);
}

function insertHeading(heading) {
var $heading = $(heading);
// what level heading are we on?
var current_level = headingLevel(heading);


// if it's an H1, add it to the original list
if (current_level === 1) {
newLi($heading, $firstUl);
$currentUl = $firstUl;
$arrayUl = [];
$arrayUl.push($firstUl);
}

// if it's the same as the one before it, add it to the current list
else if (current_level === previous_level) {
newLi($heading, $currentUl);
}

// if it's one level higher than the one before it... time to make a new nested list
else if (current_level > previous_level) {
nestUl();
$arrayUl.push($currentUl);
newLi($heading, $currentUl);
}

else if (current_level<previous_level){
for (i = 0; i < (previous_level-current_level); i++) {
$arrayUl.pop();
}
$currentUl = $arrayUl[$arrayUl.length-1];
newLi($heading, $currentUl);
}

previous_level = current_level;

var $nextHeading = $heading.nextAll("h1, h2, h3, h4, h5, h6").first()[0];
// if there's any headings left... run this again
if ($nextHeading) insertHeading($nextHeading);
}

// adds a new UL to the current UL
function nestUl() {
var $newUl = $('<ul>');
$newUl.appendTo($currentUl);
$currentUl = $newUl;
}

// returns a numerical value for each heading
function headingLevel(heading) {
switch (heading.nodeName) {
case 'H1':
return 1;
break;
case 'H2':
return 2;
break;
case 'H3':
return 3;
break;
case 'H4':
return 4;
break;
case 'H5':
return 5;
break;
case 'H6':
return 6;
break;
default:
return 0;
}
}

// inserts a new line to the current list
function newLi(heading, $list) {
var $heading = $(heading);
if ($heading.text().replace(/\s/g, '') == '') return null;
var $wrapper = $('<li></li>');
//var $link = $('<a>').prop('href', '#' + $heading.prop('id'));
var $anchorname = $heading[0].outerText.replace (/\s/g,'');
var $link = $('<a>').prop('href', '#' + $anchorname);

$link.html($heading.text());
$link.appendTo($wrapper);

$wrapper.appendTo($list);

var place_in_parent = $list.children('li').length;

$heading.html("<a name=\"" + $anchorname + "\"></a>" + $link.find('.index').text() + ' ' + $heading.text());
}
});

0


Hi Lily!

Can you post a screencap of the code you're using? That'll make it easier for us to figure out what's going wrong!

0


Hi, can someone please post a working version of this script? I've tested all of them from original to the last one and unfortunately nothing happens at all with my articles :( 

 

Thank you in advance

0


Thanks for sharing those updates!

0


and if anyone else is interested, I made a small addition to my css file to indent for subsequent levels

 

.toc ul{
padding-left: 20px;
}

0


Hey Dave, see below for how I addressed this:

Basically the code didn't account for the case when your next heading is going back a level (current_level < previous_level), so I added that case and added an array to keep track of the previous levels.

/*** Table of contents code ***/
var $headers = $('.article-body h1');

if ($headers.length > 0) {
var $toc = $('<div class="toc">');
var $firstUl = $('<ul>');
var $currentUl = $firstUl;
var previous_level = 1;
var $arrayUl = [];


$firstUl.appendTo($toc);
$toc.prependTo('section.article-info');

// start with first H1
insertHeading($headers[0]);
}

function insertHeading(heading) {
var $heading = $(heading);
// what level heading are we on?
var current_level = headingLevel(heading);


// if it's an H1, add it to the original list
if (current_level === 1) {
newLi($heading, $firstUl);
$currentUl = $firstUl;
$arrayUl = [];
$arrayUl.push($firstUl);
}

// if it's the same as the one before it, add it to the current list
else if (current_level === previous_level) {
newLi($heading, $currentUl);
}

// if it's one level higher than the one before it... time to make a new nested list
else if (current_level > previous_level) {
nestUl();
$arrayUl.push($currentUl);
newLi($heading, $currentUl);
}

else if (current_level<previous_level){
for (i = 0; i < (previous_level-current_level); i++) {
$arrayUl.pop();
}
$currentUl = $arrayUl[$arrayUl.length-1];
newLi($heading, $currentUl);
}

previous_level = current_level;

var $nextHeading = $heading.nextAll("h1, h2, h3, h4, h5, h6").first()[0];
// if there's any headings left... run this again
if ($nextHeading) insertHeading($nextHeading);
}

// adds a new UL to the current UL
function nestUl() {
var $newUl = $('<ul>');
$newUl.appendTo($currentUl);
$currentUl = $newUl;
}

// returns a numerical value for each heading
function headingLevel(heading) {
switch (heading.nodeName) {
case 'H1':
return 1;
break;
case 'H2':
return 2;
break;
case 'H3':
return 3;
break;
case 'H4':
return 4;
break;
case 'H5':
return 5;
break;
case 'H6':
return 6;
break;
default:
return 0;
}
}

// inserts a new line to the current list
function newLi(heading, $list) {
var $heading = $(heading);
var $wrapper = $('<li></li>');
//var $link = $('<a>').prop('href', '#' + $heading.prop('id'));
var $anchorname = $heading[0].outerText.replace (/\s/g,'');
var $link = $('<a>').prop('href', '#' + $anchorname);

$link.html('<span class="index"></span> ' + $heading.text());
$link.appendTo($wrapper);

$wrapper.appendTo($list);

var place_in_parent = $list.children('li').length;

if ($list.parent()[0].nodeName === 'DIV') {
$link.find('.index').text(place_in_parent)
} else {
$link.find('.index').text($wrapper.parent().prev('li').find('.index').text() + '.' + place_in_parent)
}

$heading.html("<a name=\"" + $anchorname + "\"></a>" + $link.find('.index').text() + ' ' + $heading.text());


}
});

 

0


댓글을 남기려면 로그인하세요.

추가 콘텐츠

자세히 알⁠아⁠보⁠기

원하는 정보를 못 찾으셨나요?

새 게시물