Within a pdf, you can create anchors called 'named destinations', to which a later hyperlink can refer (https://helpx.adobe.com/indesign/using/hyperlinks.html)

Is there a way to automatically turn all sections and subsections (their headings) into such anchors when working with InDesign, similar to how these are automatically turned into bookmarks?

  • I have a second document which will refer, using hyprlinks, to various (many) of the sections of this document. – LBogaardt Feb 12 '15 at 13:51
  • It certainly can be scripted. "Named destinations" must all have a unique name, so potentially just using the literal heading text is not safe (each section may have a first heading "Introduction", for example). Do you have a suggestion for this? – Jongware Feb 20 '15 at 11:50
  • Unless I misunderstood your intention, can't you use cross references instead? – Tobias Kienzler May 24 '16 at 9:21

Here is a Javascript that creates named destinations from a set of paragraph style names.

This script uses the paragraph styles and levels defined in a Table of Contents Style. That way, you can easily review and modify what styles it should use. It also needs the TOC level number; this is used to create a unique name for each destination. After the 'level' indicator, the first 16 characters of the plain text of the paragraph are copied.

(Note that this logical numbering breaks if you used lots of disconnected 'stories' in a single document -- it's not that easy to sort stories on pages. This script sorts on the internal index of stories, which, frankly, can be anything.)

When started, the script goes through your defined Table of Contents styles and ignores the empty ones. If it cannot find any eligible ones, it prompts you to to create one first.
If it finds one or more usable TOC Styles, they are shown in a small selection dialog. Select the TOC Style to use, and after pressing "OK" it goes to work. Depending on the size of your document, this can take a while.

Tested with InDesign CS4 and InDesign CC 2014.

(Some minor updates: added a space between number and text; made sure all levels don't start with '0'.)

//DESCRIPTION:Create Named Destinations for Paragraphs
// A Jongware Script 24-Feb-2015

tocstyleNames = [];
tocstyles = [];

for (i=0; i<app.activeDocument.tocStyles.length; i++)
    if (app.activeDocument.tocStyles[i].tocStyleEntries.length > 0)
        tocstyleNames.push (app.activeDocument.tocStyles[i].name);
        tocstyles.push (app.activeDocument.tocStyles[i]);

if (tocstyles.length < 1)
    alert ("Please define a TOC style first");

var wnd = new Window("dialog", "Style to Link Target");

with (wnd.add ("group"))
    with (wnd.add ("group"))
        add ('statictext', undefined, 'Use TOC style');
        var levelsDrop = add('dropdownlist', undefined, tocstyleNames);
        levelsDrop.selection = 0;
with (wnd.add ("group"))
    add ("button", undefined, "OK", {name:"ok"});
    add ("button", undefined, "Cancel", {name:"cancel"});
if (wnd.show() == 2) exit();

tocstyle = tocstyles[levelsDrop.selection.index];
styleNames = [];
lowest_level = tocstyle.tocStyleEntries[0].level;

for (i=0; i<tocstyle.tocStyleEntries.length; i++)
    styleNames.push ([app.activeDocument.paragraphStyles.item(tocstyle.tocStyleEntries[i].name), tocstyle.tocStyleEntries[i].level]);
    if (tocstyle.tocStyleEntries[i].level < lowest_level)
        lowest_level = tocstyle.tocStyleEntries[i].level;
s_len = styleNames.length;
for (i=0; i<s_len; i++)
    styleNames[i][1] -= lowest_level;

allparas = app.activeDocument.stories.everyItem().paragraphs.everyItem().getElements().reverse();

dest_list = [];

for (i=0; i<allparas.length; i++)
    for (j=0; j<s_len; j++)
        if (allparas[i].appliedParagraphStyle == styleNames[j][0])
            dest_list.push ([styleNames[j][1], make_dest (allparas[i])]);

dest_list.sort (function(a,b) {
    var aa = parseInt(a[1].name), bb = parseInt(b[1].name);
    if (aa < bb) return -1;
    if (aa > bb) return  1;
    aa = parseInt(a[1].name.substr(a[1].name.indexOf(':')+1));
    bb = parseInt(b[1].name.substr(a[1].name.indexOf(':')+1));
    return aa - bb;

// now adjust names, adding level numbers
counters = [ 0,0,0,0,0,0,0,0,0,0,0,0,0 ];

for (i=0; i<dest_list.length; i++)
    // remove story index marker
    n = dest_list[i][1].name.substring(dest_list[i][1].name.indexOf(';')+1);
    // update counters
    if (i && dest_list[i-1][0] < dest_list[i][0])
        counters[dest_list[i][0]] = 1;
    } else
    // create indexed name
    n = ' '+n;
    for (j=dest_list[i][0]; j>0; j--)
        n = String(counters[j])+'.'+n;
    dest_list[i][1].name = n;

function make_dest (a_paragraph)
    var dest = app.activeDocument.hyperlinkTextDestinations.add (a_paragraph);
    dest.name = a_paragraph.parentStory.index+':'+a_paragraph.index+';'+a_paragraph.contents.substring(0,16).replace(/\s+/g, ' ').replace(/ *\r?$/, '');
    return dest;

(Wot no syntax highlighting? 😲)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.