Developer Posted October 5, 2015 Posted October 5, 2015 Hello, I am attempting to create a document with a linked table of contents. There are two issues I am encountering. The page number is not displaying on the composed output.The hypertext link, when clicked, is not jumping to the correct destination page. Please see the attached example. Here is the code I am using for the table of contents on body page 4: myContent = ""; myContent += "Table of Contents"; myContent += '<P><P><hypertext name="TestDest"><crossref name="TestDest">'; myContent += 'Overview Section..........<$pagenum></crossref></hypertext>'; return myContent; And here is the code for the destination on body page 5: return '<destination name="TestDest">My Test Destination'; There are other FusionPro features active in this template that may be conflicting with the linked table of contents. The first 3 pages of the document are turned off through SetBodyPageUsage in the OnRecordStart rule at composition time. Also, pages from another PDF are pulled into the document using FPRepeatableComponent and overflow pages. The rules that create the FPRepeatableComponent are in the JavaScript Globals section. Are there any known limitations when using SetBodyPageUsage, FPRepeatableComponent, hypertext, and crossref page numbers all in the same document? The sample I uploaded is based on a larger document with many sections that turn on and off, and many places for user provided PDF files to be pulled into the document through template pages. I am hoping to find a solution that works with these features. One last note, I am incredibly grateful for all the users who have posted questions and answers in the past! You will find sections of code in the sample I uploaded that were previously posted in many different forum topics. I couldn't have gotten this far without the accumulated knowledge of the forums. The documentation provided with FusionPro has been very helpful as well. Any help getting all of these features to work together would be greatly appreciated!TOC_Test.zip Quote
step Posted October 6, 2015 Posted October 6, 2015 Well your first issue regarding the page number can be solved by putting the "contents" in a frame that is set to overflow. Once you do that, the <$pagenum> system variable should become available to the frame that's displaying your Table of Contents. Your second issue with the links not taking you to the correct page is a direct result of turning off pages that come before the Table of Contents. Since you turned off the first 3 pages, the count is off by 3. However, if you were to move the Table of Contents, the "content" and the overflow page for the content to the front of the document (where I would imagine a Table of Contents should go), you won't run into that issue. Understand that I get that you're just giving an example but what I'm saying is that it shouldn't be a problem for you provided your "unused" pages come after your "content". With all of that said, here's how I did it: I created the following Object Constructor which can go in your JavaScript Globals: //==================================================== // Generate a Table of Contents for a list of sections //==================================================== function TableOfContents() { this.sections = this.sections || []; this.section = function(title) { var sections = this.sections; if (sections.indexOf(title)+1) return ''; this.sections.push(title); return '<destination name="' + title + '">'; }; this.create = function(leader){ leader = leader || ''; if (!this.sections.length) { return ''; Print('No Sections Found'); } return this.sections.map(function(s){ var tab = '"0;' + (FindTextFrame(FusionPro.Composition.CurrentFlow.name).width - 100) + ',Right,,,' + leader + ';"'; return '<p br=false tabstops=' + tab + '><hypertext name="' + s+ '"><crossref name="' + s +'">' + s + '<t><$pagenum></crossref></hypertext>'; }).join('<br>'); } } Then I call it from OnRecordStart: toc = new TableOfContents; Then the "Body TC Rule" rule (the rule that returns the TOC) just becomes: return toc.create([color="Red"]'.'[/color]); Note that the "create" function accepts a parameter (highlighted in red) that defines a "leader" character for the tab between section title and page number. Also note that "Re-evaluate after every text flow" and "Treat returned strings as tagged text" are both checked. Then "Destination Rule" becomes (for example): var sections = []; // Section 1 var section1 = toc.section('Section 1') + "SECTION1" + '<br>' + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam posuere nisi in tortor sagittis dictum. Vivamus iaculis ornare neque, eu vehicula orci efficitur id. Fusce pellentesque malesuada purus id cursus. Nam quis nulla porttitor, lacinia ligula nec, porta purus. Morbi in metus est. Morbi ultricies, dui eget pharetra porta, nisl risus ultrices tortor, nec blandit turpis eros eu erat. Proin vel enim mauris. Mauris vulputate volutpat nisi eget porttitor.<br>Ut non pulvinar nisl, eget blandit enim. Integer tempor porttitor diam, in efficitur ligula elementum eget. Nam nulla enim, cursus id sagittis vel, mattis et felis. Maecenas ut lorem urna. Cras fermentum ligula in erat cursus elementum. Integer posuere nisi lobortis eros pharetra aliquam. Duis pellentesque turpis nec felis sagittis dictum. Ut mattis, mi nec aliquam porta, leo odio aliquam arcu, id ultricies neque turpis at ipsum. Donec vel urna nibh. Nullam tempus orci tincidunt tortor iaculis feugiat. Maecenas dictum, libero eget congue lobortis, erat odio eleifend nulla, id sagittis purus sem ut eros. Donec egestas consectetur dolor molestie feugiat. Donec rutrum, ante a mattis efficitur, mauris magna ultricies elit, vitae congue orci lectus vitae quam.<br>Sed vel ligula sed nunc consectetur semper. Morbi quis accumsan justo. Aliquam sit amet nisi eu libero finibus condimentum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam posuere vitae ligula pretium facilisis. Vivamus eu quam et eros dictum suscipit. Suspendisse libero augue, venenatis suscipit elit sit amet, ultricies mattis quam. Aenean faucibus nec augue at auctor. Curabitur pharetra ligula a ex lobortis vulputate.<br>Vivamus turpis enim, tincidunt vitae sollicitudin a, pellentesque in velit. Suspendisse nec fringilla neque. Donec tempus, ligula eu finibus aliquam, dolor metus blandit magna, in vestibulum nisi purus vitae nisl. Donec suscipit in metus eu placerat. Proin quis malesuada turpis. Suspendisse eget elit quis lectus ornare cursus. Morbi sed porta metus. Nam non metus id purus ultrices dignissim a vitae sapien. Duis porttitor porttitor feugiat. In hendrerit dolor nunc, quis facilisis erat varius et. Vivamus dignissim arcu porttitor dui ullamcorper aliquet.'; // Section 2 var section2 = toc.section('Section 2') + "SECTION 2" + '<br>' + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam posuere nisi in tortor sagittis dictum. Vivamus iaculis ornare neque, eu vehicula orci efficitur id. Fusce pellentesque malesuada purus id cursus. Nam quis nulla porttitor, lacinia ligula nec, porta purus. Morbi in metus est. Morbi ultricies, dui eget pharetra porta, nisl risus ultrices tortor, nec blandit turpis eros eu erat. Proin vel enim mauris. Mauris vulputate volutpat nisi eget porttitor.<br>Ut non pulvinar nisl, eget blandit enim. Integer tempor porttitor diam, in efficitur ligula elementum eget. Nam nulla enim, cursus id sagittis vel, mattis et felis. Maecenas ut lorem urna. Cras fermentum ligula in erat cursus elementum. Integer posuere nisi lobortis eros pharetra aliquam. Duis pellentesque turpis nec felis sagittis dictum. Ut mattis, mi nec aliquam porta, leo odio aliquam arcu, id ultricies neque turpis at ipsum. Donec vel urna nibh. Nullam tempus orci tincidunt tortor iaculis feugiat. Maecenas dictum, libero eget congue lobortis, erat odio eleifend nulla, id sagittis purus sem ut eros. Donec egestas consectetur dolor molestie feugiat. Donec rutrum, ante a mattis efficitur, mauris magna ultricies elit, vitae congue orci lectus vitae quam.<br>Sed vel ligula sed nunc consectetur semper. Morbi quis accumsan justo. Aliquam sit amet nisi eu libero finibus condimentum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam posuere vitae ligula pretium facilisis. Vivamus eu quam et eros dictum suscipit. Suspendisse libero augue, venenatis suscipit elit sit amet, ultricies mattis quam. Aenean faucibus nec augue at auctor. Curabitur pharetra ligula a ex lobortis vulputate.<br>Vivamus turpis enim, tincidunt vitae sollicitudin a, pellentesque in velit. Suspendisse nec fringilla neque. Donec tempus, ligula eu finibus aliquam, dolor metus blandit magna, in vestibulum nisi purus vitae nisl. Donec suscipit in metus eu placerat. Proin quis malesuada turpis. Suspendisse eget elit quis lectus ornare cursus. Morbi sed porta metus. Nam non metus id purus ultrices dignissim a vitae sapien. Duis porttitor porttitor feugiat. In hendrerit dolor nunc, quis facilisis erat varius et. Vivamus dignissim arcu porttitor dui ullamcorper aliquet.'; // Section 3 (Pulled from a rule) var section3 = Rule("section3"); sections.push(section1,section2,section3); return sections.join('<page destination="topofpage">'); Noting that the "section" function tags the destination and requires that the parameter passed be the name of the section. You can also pull in sections generated in other rules (as demonstrated above). This rule should not be set to re-evaluate during every flow. I realize that might be a little hard to follow so I've attached an example as well. Good luck!TOC_Ste.zip Quote
Developer Posted October 7, 2015 Author Posted October 7, 2015 Step, I really appreciate your detailed response and example. I have been experimenting with it all day. The table of contents object constructor is genius! It makes managing the table of contents much easier. For this particular document, I cannot think of any way around turning pages on and off before the table of contents and throughout the content area. Mainly because the main document this sample was derived from has some pages that are different sizes and have different portrait / landscape orientations, so I cannot accommodate them all with a single body and overflow page. For example, there are 9x11" divider tab pages that can be toggled on and off, mixed in with regular 8.5x11" pages. From what I understand now, I will not be able to use hypertext and destination tags for clickable links in the table of contents due to incompatibilities with SetBodyPageUsage turning pages off. On the positive side, I noticed that when I rearrange the pages in the example you provided, the hypertext links jump to the wrong pages, but the page numbers in the table of contents are correct! So I will be able to use the crossref and destination tags for correct page numbers in the table of contents, they will just not be clickable links. I will try adding PDF bookmarks through FusionPro to this document as well, and report back if they work and jump to the correct pages. Quote
step Posted October 8, 2015 Posted October 8, 2015 Step, I really appreciate your detailed response and example. I have been experimenting with it all day. The table of contents object constructor is genius! It makes managing the table of contents much easier. Thanks! I figured writing it that way would make it easily portable to other templates. And maybe it's OCD but an excessive amount of tags in a rule distract me. For this particular document, I cannot think of any way around turning pages on and off before the table of contents and throughout the content area. Mainly because the main document this sample was derived from has some pages that are different sizes and have different portrait / landscape orientations, so I cannot accommodate them all with a single body and overflow page. For example, there are 9x11" divider tab pages that can be toggled on and off, mixed in with regular 8.5x11" pages. Well I guess I'll have to take your word for that since I can't see the actual template you're trying to apply this to or seeing how you're anticipating the output to look. From what I understand now, I will not be able to use hypertext and destination tags for clickable links in the table of contents due to incompatibilities with SetBodyPageUsage turning pages off. On the positive side, I noticed that when I rearrange the pages in the example you provided, the hypertext links jump to the wrong pages, but the page numbers in the table of contents are correct! So I will be able to use the crossref and destination tags for correct page numbers in the table of contents, they will just not be clickable links. Right. The page numbers will be correct but I think the interactive link that FP generates is written prior to the actual page number (after body pages are turned off) being determined. The object constructor can be re-written like this to remove the hyperlinks: //==================================================== // Generate a Table of Contents for a list of sections //==================================================== function TableOfContents() { this.sections = this.sections || []; this.section = function(title) { var sections = this.sections; if (sections.indexOf(title)+1) return ''; this.sections.push(title); return '<destination name="' + title + '">'; }; this.create = function(leader){ leader = leader || ''; if (!this.sections.length) { return ''; Print('No Sections Found'); } return this.sections.map(function(s){ var tab = '"0;' + (FindTextFrame(FusionPro.Composition.CurrentFlow.name).width - 100) + ',Right,,,' + leader + ';"'; return '<p br=false tabstops=' + tab + '><crossref name="' + s +'">' + s + '<t><$pagenum></crossref>'; }).join('<br>'); } } I will try adding PDF bookmarks through FusionPro to this document as well, and report back if they work and jump to the correct pages. I'm pretty sure that bookmarks will jump to the correct pages regardless of the pages that have been turned on/off. If you wanted to make bookmarking an option in the object constructor, you could change it to: //==================================================== // Generate a Table of Contents for a list of sections //==================================================== function TableOfContents() { this.bookmarks = this.bookmarks; this.sections = this.sections || []; this.section = function(title) { var sections = this.sections; if (sections.indexOf(title)+1) return ''; this.sections.push(title); var tags = this.bookmarks ? '<p bookmarked="True">' + title + '<p>' : ''; tags +='<destination name="' + title + '">'; return tags; }; this.create = function(leader){ leader = leader || ''; if (!this.sections.length) { return ''; Print('No Sections Found'); } return this.sections.map(function(s){ var tab = '"0;' + (FindTextFrame(FusionPro.Composition.CurrentFlow.name).width - 100) + ',Right,,,' + leader + ';"'; return '<p br=false tabstops=' + tab + '><hypertext name="' + s+ '"><crossref name="' + s +'">' + s + '<t><$pagenum></crossref></hypertext>'; }).join('<br>'); } } And in OnRecordStart: toc = new TableOfContents; toc.bookmarks = true; Quote
Developer Posted October 12, 2015 Author Posted October 12, 2015 Yes! I tested, and can confirm that bookmarks jump to the correct page number, even when turning pages on and off with SetBodyPageUsage. This is a great relief. Although hypertext will not work in the table of contents (in this particular scenario), bookmarks will compensate for some of the lost functionality. Thank you for the updated sample code as well! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.