3 Replies Latest reply on Feb 5, 2013 2:48 AM by [Jongware]

    Generate a formatted list of cross references in order?

    ArmstrongP

      Hi all, wondering if anyone has any scripts / advice that could help me out. Here's my situation:

       

      I have a ~250 page document with a lot of named text anchors placed throughout one long story.

       

      I want to generate an appendix – a formatted list at the end of the document, of cross references, in the order they appear in the text, in a format like this:

       

      P<page no>, <name of reference>: Note about this cross reference.

       

      Where:

       

      - the <page no> and <name of reference> are drawn from the text anchor in the main text of the document

      - the "Note about this cross reference" is manually typed in to the reference list.

      - <page no> is wrapped in a character style so I can set up a running header in the appendix, along the lines of "Notes to pages X to Y"

       

      I can of course make them manually using a custom cross reference format, but this is pretty laborious, and means I can't really shuffle pages/paras around in the main text without redoing the whole appendix manually.

       

      Any thoughts appreciated! I have a decent handle on Javascript in a web development context but haven't used it to script InDesign before.

       

      Thanks

      Pat

        • 1. Re: Generate a formatted list of cross references in order?
          [Jongware] Most Valuable Participant

          Line by line, thinking-while-typing, and commented as well! Please do try the "try this" snippets.

           

          // Let's grab a shortcut to the xrefs. These are, internally,
          // a certain type of Hyperlink.
          xrefs = app.activeDocument.hyperlinkTextDestinations;
          
          // xrefs now holds a pointer to the 'destinations'
          // These are the inserted X-Refs.
          // Try this:
          // alert (xrefs.length);
          // See?
          
          // The x-ref property *destinationText* points to the actual 'insertion point', which
          // is the position inside your text of the nigh-on invisible code.
          // Try this:
          // xrefs[0].destinationText.select();
          // -- it will select the invisible character (move your cursor slightly to
          // have ID jump to the correct page).
          
          // Since it's a Text object, you can find out the page its on using this:
          // alert (xrefs[0].destinationText.parentTextFrames[0].parentPage.name);
          // .. to go from Text to Page, you need a detour through parentTextFrames.
          
          // The 'name' of the xref is simply its name property:
          // alert (xrefs[0].name);
          
          // With all that, you can loop over all of your xrefs and write them out.
          // for (i=0; i<xrefs.length; i++)
          //   ... 
          // But wait! You want them sorted by page!
          // So you need to store them first into an array, sort all, and *then* write.
          
          var xrefNames = [];
          
          for (i=0; i<xrefs.length; i++)
          {
                    xrefNames.push ( [ xrefs[i].destinationText.parentTextFrames[0].parentPage.documentOffset,
                              xrefs[i].destinationText.parentTextFrames[0].parentPage.name,
                              xrefs[i].name ]);
          }
          
          // I'm storing 'page.documentOffset', rather than 'page.name', because (1) "name" can be
          // either "1", "12", "XLC", or "AB" -- 'logical' page numbers --, and those compare badly,
          // in a numerical sense, and (2) you could have two sections, each starting with page 1 again
          // (a bad practice, but ID allows it). 'documentOffset', on the other hand, is the *physical*
          // page number.
          
          xrefNames.sort ( function(a,b) { return a[0] - b[0]; } );
          
          // Want to see them? Use this:
          // alert (xrefNames.join('\r'));
          
          // Now we have the list, let's find a place to write'em to. This code checks if your
          // text cursor is 'inside' a text frame.
          // ... It's one of those fragments I know from heart but cannot recall who came up
          // with it first! It checks for a selection *length* -- even a single blinking cursor has
          // a 'selected' length, albeit the selected *text* is always 0 characters long --, and,
          // if so, if you can write text to it. All Text based objects have a shared property called
          // "baseline", so ...
          if (app.selection.length != 1 || !app.selection[0].hasOwnProperty("baseline"))
          {
                    alert ("Please place the text cursor inside a text frame");
                    exit();
          }
          
          // Coming here, it's time to write something out. Let's first grab a pointer to
          // the character style for the initial text.
          // Be sure to fill in the right Character Style name.
          cStyle = app.activeDocument.characterStyles.item("YourCharStyleName");
          
          // Dummy check 
          // Accessing the name, even this way, while it doesn't exist, will yield an
          // error:
          try {
                    cStyle.name;
          } catch (e)
          {
                    alert ("Yeah that style name does not exist...");
                    exit();
          }
          
          // Oh wait, it *does*. Write out the list.
          
          for (i=0; i<xrefNames.length; i++)
          {
                    // Set character style ...
                    app.selection[0].insertionPoints[-1].appliedCharacterStyle = cStyle;
                    // Write out "P" plus page ...
                    // (use the 'real' name here, second element in our custom array)
                    app.selection[0].insertionPoints[-1].contents = 'P' + xrefNames[i][1];
                    // Reset character style ...
                    // (item [0] is always [None])
                    app.selection[0].insertionPoints[-1].appliedCharacterStyle = app.activeDocument.characterStyles[0];
                    // .. add name ..
                    app.selection[0].insertionPoints[-1].contents = ', '+xrefNames[i][2];
                    // .. your own stuff ..
                    app.selection[0].insertionPoints[-1].contents = ': Note ...';
                    // .. and a Hard Return for good luck.
                    app.selection[0].insertionPoints[-1].contents = '\r';
          }
          
          // Now wasn't that fun!
          

           

          My very first Javascript must have been some plain-copied IE or Netscape code, back when Browser Wars Raged -- you know, perhaps some animated button or banner code. The very first JS I actually created from scratch was for ... Photoshop! (Saving cover images in a variety of sizes and file formats. I've been told my previous workplace still uses it, after more than a decade.) I cannot even recall the exact circumstances on how I got "in" to ID scripting ... but then there were some giants out here on this forum, and all I did was step on shoulders (and occasionally on some toes as well).

           

          Enjoy!

          • 2. Re: Generate a formatted list of cross references in order?
            ArmstrongP Level 1

            Wow, thanks Jongware!

             

            I'm not at my work machine at the moment, but I'll be able to try this out in a few hours (including the "try this" bits!) and let you know how I go.

             

            Cheers & thanks again,

            Pat

            • 3. Re: Generate a formatted list of cross references in order?
              [Jongware] Most Valuable Participant

              Intermittant thought:

               

              I can of course make them manually using a custom cross reference format, but this is pretty laborious, and means I can't really shuffle pages/paras around in the main text without redoing the whole appendix manually.

               

              .. my script builds up the list from scratch, so your manual notes would not get carried along and you'd have to re-type them. Theoretically, it's possible to insert the text not as "plain" text, but in the cross reference format you propose. However, then you run into problems with sorting your list!

               

              A solution could be this: you can add *custom* data to a lot of native InDesign objects in the form of a "label" -- a key/value pair. Perhaps it's possible to add the text of your notes to each of the x-refs themselves, and have this script write them out as text. Adding and editing custom labels to an xref object is not possible with the regular interface, so this would need a second script.