Summary: Handy Client-side Table of Contents
Version: 2017-09-07
Prerequisites: PmWiki 2.2.56
Status: stable
Maintainer: Kathryn Andersen
Categories: TOC, Markup, PHP5, PHP72

Questions answered by this recipe

How can I create a table of contents for included files? How can I create a table of contents for a page whose content is generated via pagelist?


Most of the existing table-of-contents recipes have this limitation: they can only generate a table of contents from the information in the source of the page they're used in. If data is included later (either with (:include :), or, even more tricky, with IncludeUpload) then they don't have the data to base the table-of-contents on.

This recipe solves that problem by generating the table-of-contents with JavaScript, which is run after the page has finished loading, so all the data is there.

Of course, the downside is that it requires JavaScript to be turned on; which many users and browsers may not. Caveat emptor.



To activate this recipe, unzip the archive; this will create a handytoc-(version) directory; you then need to move or copy the contents of this into your pmwiki directory. The directory contains:

File contains markup and functions.
Directory contains CSS and JavaScript files.

Add the following line to your local/config.php:



The simplest usage is to just put the (:htoc:) directive on the page where you want to have a table-of-contents.

You can add a title to your table of contents simply by adding it to the directive:

(:htoc This is my table of contents:)

There are also options.

startstart=2What level of header the table of contents starts at
endend=3What level of header the table of contents ends at
ignoreh1ignoreh1=trueThe ignoreh1= option can be either true or false. If true, then if there is only one H1 header in the content, then it will be ignored. If false, it won't be (providing that the start option equals 1).
classclass=htonelineset the class name for the div that the table of contents is inside. Useful for additional CSS styling for different kinds of ToCs.
anchorafterlementanchorafterelement=trueCan be true or false. If true, anchor is inserted after a heading (equivalent of !!! MyCoolHeading [[#tocLink9]]). If false, before (equivalent of !!! [[#tocLink9]] MyCoolHeading). This affects whether the heading is visible on the page after clicking on a link in the ToC.


(:htoc start=2:)

The above will start with h2 headers.

(:htoc end=3:)

The above will end at h3 headers.

Note that if there are no H1 headers inside the content at all, then the table-of-contents will start at level 2 automatically (unless a greater start level is already specified), even of the headers are in an odd order.

Configuration variables

These can be set in local/config.php

$HandyTocStartAtDefine the (default) level the table-of-contents starts at1
$HandyTocEndAtDefine the (default) level the table-of-contents ends at6
$HandyTocIgnoreSoleH1If 'true', then if there's only one h1 header in the content, it will be ignored.'true'
$HandyTocPubDirUrlUrl of directory where the HandyToc css and js files are$FarmPubDirUrl/handytoc
$HandyTocAnchorAfterElementIf true, anchor is inserted after heading; otherwise, before.true
$HandyTocDefaultTitleProvides the default title, if none is provided in the page directive.empty (no title)

CSS Styling

The table of contents is put inside a div with id='htoc', and the table-of-contents title (if there is one) is put in a H3 header. The <ul> element in the div has id='htoc_ul'. While the recipe comes with its own CSS styling (in pub/handytoc/handytoc.css) this can be overridden with your own custom CSS in pub/css/local.css

If the "class=" option is used, then the class is set for the same div; that is, it will be

    <div id="htoc" class="classname">

so keep that in mind when using this option.

There is also a .htoneline (handy-toc one line) class in the CSS file, which can be used (with the "class=" option) to make the table-of-contents all on one line, with | separators between each item. This is useful for pages where the headers are, say, single letters of the alphabet (as may happen with indexes). The CSS for this, however, may not work in less-advanced browsers.


This does not have a show/hide button like some of the other TOC recipes; if it's defined for that page, then it's there all the time. If you want to show and hide the toc, you can use the Show Hide recipe with markup such as the following:

(:showhide init=hide div=htoc lshow='Show Table of Contents' lhide='Hide Table of Contents':)

Note that this recipe will not work if the skin you are using does not have <!--HTMLFooter--> markup in it.

Release Notes

  • 2017-09-07: Fixed bug that would sometimes prevent the ToC from being created if $EnableHTMLCache was set.
  • 2017-08-22: Added id of htoc_ul to the <ul> element inside the #htoc div (to allow just the list to be shown/hidden by Toggle).
  • 2017-08-16: Added $HandyTocDefaultTitle.
  • 2017-08-16: Added $HandyTocAnchorAfterElement; fixed bug where "start"/$HandyTocStartAt would have no effect in many cases.
  • 2017-06-21: changed Markup for PHP 7.2 compatibility (HansB)
  • 2016-09-02: HansB: update for PHP5 compatibility.
  • (2007-02-18) Added "class=" option, and .htoneline CSS class
  • (2007-02-17) Put the JavaScript calls into $HTMLFooterFmt only if the markup is present.
  • (2007-02-11) Added $HandyTocIgnoreSoleH1 and ignore=h1
  • (2007-02-08) Now only looks inside #wikitext (page content); also fixed problems with different header levels in random order. Now XHTML compliant!
  • (2007-02-07a) fixed overlooked bug (forgot to rename something)
  • (2007-02-07) Initial version

See Also

Cookbook /
Accordion  lightweight Accordion javascript requiring no framework (stable)
AutoTOC  Unobtrusive Automatic Table of Contents links (stable)
NumberedHeaders  Display numbered headers, indented paragraphs and table of contents (Stable)
NumberedSections  Add section numbers on a page (stable)
PageTableOfContents  Adds a clickable table of contents to a page (Stable)
QuickPageTableOfContents  Adds a dropdown clickable table of contents to a page - client side processing (Stable)
SlimTableOfContents  Simple or Numbered Table of Contents, Compatible with SectionEdit Recipe (not working with php5.5)
TableOfContentsPortion  Inserts a portion of external table of contents into the page (Alpha)



See discussion at HandyTableOfContents-Talk

User notes +3: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.